OSDN Git Service

[Refactor] #37353 混乱時のコマンド制限処理を cmd_limit_confused() に統合。 / Integrate command limitat...
[hengband/hengband.git] / src / cmd-spell.c
index 9939d57..38ff3c8 100644 (file)
@@ -8,7 +8,6 @@
 \r
 #include "angband.h"\r
 #include "selfinfo.h"\r
-#include "cmd-quaff.h"\r
 #include "spells-summon.h"\r
 #include "realm-arcane.h"\r
 #include "realm-chaos.h"\r
 #include "realm-crusade.h"\r
 #include "realm-daemon.h"\r
 #include "realm-death.h"\r
+#include "realm-hex.h"\r
+#include "realm-hissatsu.h"\r
 #include "realm-life.h"\r
 #include "realm-nature.h"\r
+#include "realm-song.h"\r
 #include "realm-sorcery.h"\r
 #include "realm-trump.h"\r
+#include "angband.h"\r
+#include "avatar.h"\r
+#include "player-status.h"\r
+#include "object-hook.h"\r
 \r
 /*!\r
  * @brief\r
@@ -30,7 +36,7 @@
  * @param base 固定値\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_string_dice(cptr str, int dice, int sides, int base)\r
+concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base)\r
 {\r
        /* Fix value */\r
        if (!dice)\r
@@ -53,7 +59,7 @@ cptr info_string_dice(cptr str, int dice, int sides, int base)
  * @param base 固定値\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_damage(int dice, int sides, int base)\r
+concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base)\r
 {\r
        return info_string_dice(_("損傷:", "dam "), dice, sides, base);\r
 }\r
@@ -64,7 +70,7 @@ cptr info_damage(int dice, int sides, int base)
  * @param sides ダイス目\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_duration(int base, int sides)\r
+concptr info_duration(int base, DICE_SID sides)\r
 {\r
        return format(_("期間:%d+1d%d", "dur %d+1d%d"), base, sides);\r
 }\r
@@ -74,7 +80,7 @@ cptr info_duration(int base, int sides)
  * @param range 効果範囲\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_range(POSITION range)\r
+concptr info_range(POSITION range)\r
 {\r
        return format(_("範囲:%d", "range %d"), range);\r
 }\r
@@ -86,7 +92,7 @@ cptr info_range(POSITION range)
  * @param base 固定値\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_heal(int dice, int sides, int base)\r
+concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base)\r
 {\r
        return info_string_dice(_("回復:", "heal "), dice, sides, base);\r
 }\r
@@ -97,7 +103,7 @@ cptr info_heal(int dice, int sides, int base)
  * @param sides ダイス目\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_delay(int base, int sides)\r
+concptr info_delay(int base, DICE_SID sides)\r
 {\r
        return format(_("遅延:%d+1d%d", "delay %d+1d%d"), base, sides);\r
 }\r
@@ -108,7 +114,7 @@ cptr info_delay(int base, int sides)
  * @param dam 固定値\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_multi_damage(HIT_POINT dam)\r
+concptr info_multi_damage(HIT_POINT dam)\r
 {\r
        return format(_("損傷:各%d", "dam %d each"), dam);\r
 }\r
@@ -120,7 +126,7 @@ cptr info_multi_damage(HIT_POINT dam)
  * @param sides ダイス目\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_multi_damage_dice(int dice, int sides)\r
+concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides)\r
 {\r
        return format(_("損傷:各%dd%d", "dam %dd%d each"), dice, sides);\r
 }\r
@@ -130,7 +136,7 @@ cptr info_multi_damage_dice(int dice, int sides)
  * @param power 固定値\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_power(int power)\r
+concptr info_power(int power)\r
 {\r
        return format(_("効力:%d", "power %d"), power);\r
 }\r
@@ -145,7 +151,7 @@ cptr info_power(int power)
 /*\r
  * Generate power info string such as "power 1d100"\r
  */\r
-cptr info_power_dice(int dice, int sides)\r
+concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides)\r
 {\r
        return format(_("効力:%dd%d", "power %dd%d"), dice, sides);\r
 }\r
@@ -156,7 +162,7 @@ cptr info_power_dice(int dice, int sides)
  * @param rad 効果半径\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_radius(int rad)\r
+concptr info_radius(POSITION rad)\r
 {\r
        return format(_("半径:%d", "rad %d"), rad);\r
 }\r
@@ -167,7 +173,7 @@ cptr info_radius(int rad)
  * @param weight 最大重量\r
  * @return フォーマットに従い整形された文字列\r
  */\r
-cptr info_weight(int weight)\r
+concptr info_weight(WEIGHT weight)\r
 {\r
 #ifdef JP\r
        return format("最大重量:%d.%dkg", lbtokg1(weight), lbtokg2(weight));\r
@@ -176,2804 +182,1214 @@ cptr info_weight(int weight)
 #endif\r
 }\r
 \r
-\r
 /*!\r
- * @brief 歌の開始を処理する / Start singing if the player is a Bard \r
- * @param spell 領域魔法としてのID\r
- * @param song 魔法効果のID\r
- * @return なし\r
+ * @brief 魔法処理のメインルーチン\r
+ * @param realm 魔法領域のID\r
+ * @param spell 各領域の魔法ID\r
+ * @param mode 求める処理\r
+ * @return 各領域魔法に各種テキストを求めた場合は文字列参照ポインタ、そうでない場合はNULLポインタを返す。\r
  */\r
-static void start_singing(SPELL_IDX spell, MAGIC_NUM1 song)\r
+concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode)\r
 {\r
-       /* Remember the song index */\r
-       SINGING_SONG_EFFECT(p_ptr) = (MAGIC_NUM1)song;\r
+       switch (realm)\r
+       {\r
+       case REALM_LIFE:     return do_life_spell(spell, mode);\r
+       case REALM_SORCERY:  return do_sorcery_spell(spell, mode);\r
+       case REALM_NATURE:   return do_nature_spell(spell, mode);\r
+       case REALM_CHAOS:    return do_chaos_spell(spell, mode);\r
+       case REALM_DEATH:    return do_death_spell(spell, mode);\r
+       case REALM_TRUMP:    return do_trump_spell(spell, mode);\r
+       case REALM_ARCANE:   return do_arcane_spell(spell, mode);\r
+       case REALM_CRAFT:    return do_craft_spell(spell, mode);\r
+       case REALM_DAEMON:   return do_daemon_spell(spell, mode);\r
+       case REALM_CRUSADE:  return do_crusade_spell(spell, mode);\r
+       case REALM_MUSIC:    return do_music_spell(spell, mode);\r
+       case REALM_HISSATSU: return do_hissatsu_spell(spell, mode);\r
+       case REALM_HEX:      return do_hex_spell(spell, mode);\r
+       }\r
 \r
-       /* Remember the index of the spell which activated the song */\r
-       SINGING_SONG_ID(p_ptr) = (MAGIC_NUM2)spell;\r
+       return NULL;\r
+}\r
 \r
 \r
-       /* Now the player is singing */\r
-       set_action(ACTION_SING);\r
+/*!\r
+ * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理\r
+ * Allow user to choose a spell/prayer from the given book.\r
+ * @param sn 選択した魔法IDを返す参照ポインタ\r
+ * @param prompt 魔法を利用する際の動詞表記\r
+ * @param sval 魔道書のsval\r
+ * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE\r
+ * @param use_realm 魔法領域ID\r
+ * @return\r
+ * <pre>\r
+ * If a valid spell is chosen, saves it in '*sn' and returns TRUE\r
+ * If the user hits escape, returns FALSE, and set '*sn' to -1\r
+ * If there are no legal choices, returns FALSE, and sets '*sn' to -2\r
+ * The "prompt" should be "cast", "recite", or "study"\r
+ * The "known" should be TRUE for cast/pray, FALSE for study\r
+ * </pre>\r
+ */\r
+static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm)\r
+{\r
+       int i;\r
+       SPELL_IDX spell = -1;\r
+       int num = 0;\r
+       int ask = TRUE;\r
+       MANA_POINT need_mana;\r
+       SPELL_IDX spells[64];\r
+       bool flag, redraw, okay;\r
+       char choice;\r
+       const magic_type  *s_ptr;\r
+       char out_val[160];\r
+       concptr p;\r
+       COMMAND_CODE code;\r
+#ifdef JP\r
+       char jverb_buf[128];\r
+#endif\r
+       int menu_line = (use_menu ? 1 : 0);\r
+\r
+       /* Get the spell, if available */\r
+       if (repeat_pull(&code))\r
+       {\r
+               *sn = (SPELL_IDX)code;\r
+               /* Verify the spell */\r
+               if (spell_okay(*sn, learned, FALSE, use_realm))\r
+               {\r
+                       /* Success */\r
+                       return (TRUE);\r
+               }\r
+       }\r
 \r
+       p = spell_category_name(mp_ptr->spell_book);\r
 \r
-       /* Recalculate bonuses */\r
-       p_ptr->update |= (PU_BONUS);\r
+       /* Extract spells */\r
+       for (spell = 0; spell < 32; spell++)\r
+       {\r
+               /* Check for this spell */\r
+               if ((fake_spell_flags[sval] & (1L << spell)))\r
+               {\r
+                       /* Collect this spell */\r
+                       spells[num++] = spell;\r
+               }\r
+       }\r
 \r
-       /* Redraw status bar */\r
-       p_ptr->redraw |= (PR_STATUS);\r
-}\r
+       /* Assume no usable spells */\r
+       okay = FALSE;\r
 \r
-/*!\r
- * @brief 歌の停止を処理する / Stop singing if the player is a Bard \r
- * @return なし\r
- */\r
-void stop_singing(void)\r
-{\r
-       if (p_ptr->pclass != CLASS_BARD) return;\r
+       /* Assume no spells available */\r
+       (*sn) = -2;\r
 \r
-       /* Are there interupted song? */\r
-       if (INTERUPTING_SONG_EFFECT(p_ptr))\r
+       /* Check for "okay" spells */\r
+       for (i = 0; i < num; i++)\r
        {\r
-               /* Forget interupted song */\r
-               INTERUPTING_SONG_EFFECT(p_ptr) = MUSIC_NONE;\r
-               return;\r
+               /* Look for "okay" spells */\r
+               if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE;\r
        }\r
 \r
-       /* The player is singing? */\r
-       if (!SINGING_SONG_EFFECT(p_ptr)) return;\r
+       /* No "okay" spells */\r
+       if (!okay) return (FALSE);\r
+       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
+       if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE;\r
+       if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE;\r
 \r
-       /* Hack -- if called from set_action(), avoid recursive loop */\r
-       if (p_ptr->action == ACTION_SING) set_action(ACTION_NONE);\r
+       /* Assume cancelled */\r
+       *sn = (-1);\r
 \r
-       /* Message text of each song or etc. */\r
-       do_spell(REALM_MUSIC, SINGING_SONG_ID(p_ptr), SPELL_STOP);\r
+       /* Nothing chosen yet */\r
+       flag = FALSE;\r
 \r
-       SINGING_SONG_EFFECT(p_ptr) = MUSIC_NONE;\r
-       SINGING_SONG_ID(p_ptr) = 0;\r
+       /* No redraw yet */\r
+       redraw = FALSE;\r
 \r
-       /* Recalculate bonuses */\r
-       p_ptr->update |= (PU_BONUS);\r
+       p_ptr->window |= (PW_SPELL);\r
+       handle_stuff();\r
 \r
-       /* Redraw status bar */\r
-       p_ptr->redraw |= (PR_STATUS);\r
-}\r
+       /* Build a prompt (accept all spells) */\r
+#ifdef JP\r
+       jverb(prompt, jverb_buf, JVERB_AND);\r
+       (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ",\r
+               p, I2A(0), I2A(num - 1), p, jverb_buf);\r
+#else\r
+       (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ",\r
+               p, I2A(0), I2A(num - 1), prompt, p);\r
+#endif\r
 \r
-/*!\r
- * @brief 歌の各処理を行う\r
- * @param spell 歌ID\r
- * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST / SPELL_FAIL / SPELL_CONT / SPELL_STOP)\r
- * @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST / SPELL_FAIL / SPELL_CONT / SPELL_STOP 時はNULL文字列を返す。\r
- */\r
-static cptr do_music_spell(SPELL_IDX spell, BIT_FLAGS mode)\r
-{\r
-       bool name = (mode == SPELL_NAME) ? TRUE : FALSE;\r
-       bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;\r
-       bool info = (mode == SPELL_INFO) ? TRUE : FALSE;\r
-       bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;\r
-       bool fail = (mode == SPELL_FAIL) ? TRUE : FALSE;\r
-       bool cont = (mode == SPELL_CONT) ? TRUE : FALSE;\r
-       bool stop = (mode == SPELL_STOP) ? TRUE : FALSE;\r
-       static const char s_dam[] = _("損傷:", "dam ");\r
-\r
-       int dir;\r
-       int plev = p_ptr->lev;\r
-\r
-       switch (spell)\r
+       /* Get a spell from the user */\r
+\r
+       choice = (always_show_list || use_menu) ? ESCAPE : 1;\r
+       while (!flag)\r
        {\r
-       case 0:\r
-               if (name) return _("遅鈍の歌", "Song of Holding");\r
-               if (desc) return _("視界内の全てのモンスターを減速させる。抵抗されると無効。", "Attempts to slow all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
-\r
-               if (cast)\r
-               {\r
-                       msg_print(_("ゆっくりとしたメロディを口ずさみ始めた...", "You start humming a slow, steady melody..."));\r
-                       start_singing(spell, MUSIC_SLOW);\r
-               }\r
+               if (choice == ESCAPE) choice = ' ';\r
+               else if (!get_com(out_val, &choice, TRUE))break;\r
 \r
+               if (use_menu && choice != ' ')\r
                {\r
-                       int power = plev;\r
-\r
-                       if (info) return info_power(power);\r
-\r
-                       if (cont)\r
+                       switch (choice)\r
+                       {\r
+                       case '0':\r
                        {\r
-                               slow_monsters(plev);\r
+                               screen_load();\r
+                               return FALSE;\r
                        }\r
-               }\r
-               break;\r
 \r
-       case 1:\r
-               if (name) return _("祝福の歌", "Song of Blessing");\r
-               if (desc) return _("命中率とACのボーナスを得る。", "Gives bonus to hit and AC for a few turns.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+                       case '8':\r
+                       case 'k':\r
+                       case 'K':\r
+                       {\r
+                               menu_line += (num - 1);\r
+                               break;\r
+                       }\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("厳かなメロディを奏で始めた...", "The holy power of the Music of the Ainur enters you..."));\r
-                       start_singing(spell, MUSIC_BLESS);\r
-               }\r
+                       case '2':\r
+                       case 'j':\r
+                       case 'J':\r
+                       {\r
+                               menu_line++;\r
+                               break;\r
+                       }\r
 \r
-               if (stop)\r
-               {\r
-                       if (!p_ptr->blessed)\r
+                       case 'x':\r
+                       case 'X':\r
+                       case '\r':\r
+                       case '\n':\r
                        {\r
-                               msg_print(_("高潔な気分が消え失せた。", "The prayer has expired."));\r
+                               i = menu_line - 1;\r
+                               ask = FALSE;\r
+                               break;\r
                        }\r
+                       }\r
+                       if (menu_line > num) menu_line -= num;\r
+                       /* Display a list of spells */\r
+                       print_spells(menu_line, spells, num, 1, 15, use_realm);\r
+                       if (ask) continue;\r
                }\r
+               else\r
+               {\r
+                       /* Request redraw */\r
+                       if ((choice == ' ') || (choice == '*') || (choice == '?'))\r
+                       {\r
+                               /* Show the list */\r
+                               if (!redraw)\r
+                               {\r
+                                       /* Show list */\r
+                                       redraw = TRUE;\r
+                                       screen_save();\r
 \r
-               break;\r
+                                       /* Display a list of spells */\r
+                                       print_spells(menu_line, spells, num, 1, 15, use_realm);\r
+                               }\r
 \r
-       case 2:\r
-               if (name) return _("崩壊の音色", "Wrecking Note");\r
-               if (desc) return _("轟音のボルトを放つ。", "Fires a bolt of sound.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+                               /* Hide the list */\r
+                               else\r
+                               {\r
+                                       if (use_menu) continue;\r
 \r
-               {\r
-                       int dice = 4 + (plev - 1) / 5;\r
-                       int sides = 4;\r
+                                       /* Hide list */\r
+                                       redraw = FALSE;\r
+                                       screen_load();\r
+                               }\r
 \r
-                       if (info) return info_damage(dice, sides, 0);\r
+                               /* Redo asking */\r
+                               continue;\r
+                       }\r
 \r
-                       if (cast)\r
-                       {\r
-                               if (!get_aim_dir(&dir)) return NULL;\r
 \r
-                               fire_bolt(GF_SOUND, dir, damroll(dice, sides));\r
-                       }\r
-               }\r
-               break;\r
+                       /* Note verify */\r
+                       ask = (isupper(choice));\r
 \r
-       case 3:\r
-               if (name) return _("朦朧の旋律", "Stun Pattern");\r
-               if (desc) return _("視界内の全てのモンスターを朦朧させる。抵抗されると無効。", "Attempts to stun all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+                       /* Lowercase */\r
+                       if (ask) choice = (char)tolower(choice);\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("眩惑させるメロディを奏で始めた...", "You weave a pattern of sounds to bewilder and daze..."));\r
-                       start_singing(spell, MUSIC_STUN);\r
+                       /* Extract request */\r
+                       i = (islower(choice) ? A2I(choice) : -1);\r
                }\r
 \r
+               /* Totally Illegal */\r
+               if ((i < 0) || (i >= num))\r
                {\r
-                       int dice = plev / 10;\r
-                       int sides = 2;\r
-\r
-                       if (info) return info_power_dice(dice, sides);\r
-\r
-                       if (cont)\r
-                       {\r
-                               stun_monsters(damroll(dice, sides));\r
-                       }\r
+                       bell();\r
+                       continue;\r
                }\r
 \r
-               break;\r
-\r
-       case 4:\r
-               if (name) return _("生命の流れ", "Flow of Life");\r
-               if (desc) return _("体力を少し回復させる。", "Heals HP a little.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+               /* Save the spell index */\r
+               spell = spells[i];\r
 \r
-               if (cast)\r
+               /* Require "okay" spells */\r
+               if (!spell_okay(spell, learned, FALSE, use_realm))\r
                {\r
-                       msg_print(_("歌を通して体に活気が戻ってきた...", "Life flows through you as you sing a song of healing..."));\r
-                       start_singing(spell, MUSIC_L_LIFE);\r
+                       bell();\r
+#ifdef JP\r
+                       msg_format("その%sを%sことはできません。", p, prompt);\r
+#else\r
+                       msg_format("You may not %s that %s.", prompt, p);\r
+#endif\r
+\r
+                       continue;\r
                }\r
 \r
+               /* Verify it */\r
+               if (ask)\r
                {\r
-                       int dice = 2;\r
-                       int sides = 6;\r
+                       char tmp_val[160];\r
 \r
-                       if (info) return info_heal(dice, sides, 0);\r
-\r
-                       if (cont)\r
+                       /* Access the spell */\r
+                       if (!is_magic(use_realm))\r
                        {\r
-                               hp_player(damroll(dice, sides));\r
+                               s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
                        }\r
-               }\r
-\r
-               break;\r
-\r
-       case 5:\r
-               if (name) return _("太陽の歌", "Song of the Sun");\r
-               if (desc) return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
-\r
-               {\r
-                       int dice = 2;\r
-                       int sides = plev / 2;\r
-                       int rad = plev / 10 + 1;\r
-\r
-                       if (info) return info_damage(dice, sides, 0);\r
-\r
-                       if (cast)\r
+                       else\r
                        {\r
-                               msg_print(_("光り輝く歌が辺りを照らした。", "Your uplifting song brings brightness to dark places..."));\r
-                               lite_area(damroll(dice, sides), rad);\r
+                               s_ptr = &mp_ptr->info[use_realm - 1][spell];\r
                        }\r
-               }\r
-               break;\r
 \r
-       case 6:\r
-               if (name) return _("恐怖の歌", "Song of Fear");\r
-               if (desc) return _("視界内の全てのモンスターを恐怖させる。抵抗されると無効。", "Attempts to scare all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
-\r
-               if (cast)\r
-               {\r
-                       msg_print(_("おどろおどろしいメロディを奏で始めた...", "You start weaving a fearful pattern..."));\r
-                       start_singing(spell, MUSIC_FEAR);                       \r
-               }\r
+                       /* Extract mana consumption rate */\r
+                       if (use_realm == REALM_HISSATSU)\r
+                       {\r
+                               need_mana = s_ptr->smana;\r
+                       }\r
+                       else\r
+                       {\r
+                               need_mana = mod_need_mana(s_ptr->smana, spell, use_realm);\r
+                       }\r
 \r
-               {\r
-                       int power = plev;\r
+                       /* Prompt */\r
+#ifdef JP\r
+                       jverb(prompt, jverb_buf, JVERB_AND);\r
+                       /* 英日切り替え機能に対応 */\r
+                       (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ",\r
+                               do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
+                               spell_chance(spell, use_realm), jverb_buf);\r
+#else\r
+                       (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ",\r
+                               prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
+                               spell_chance(spell, use_realm));\r
+#endif\r
 \r
-                       if (info) return info_power(power);\r
 \r
-                       if (cont)\r
-                       {\r
-                               project_hack(GF_TURN_ALL, power);\r
-                       }\r
+                       /* Belay that order */\r
+                       if (!get_check(tmp_val)) continue;\r
                }\r
 \r
-               break;\r
+               /* Stop the loop */\r
+               flag = TRUE;\r
+       }\r
 \r
-       case 7:\r
-               if (name) return _("戦いの歌", "Heroic Ballad");\r
-               if (desc) return _("ヒーロー気分になる。", "Removes fear, and gives bonus to hit and 10 more HP for a while.");\r
+       if (redraw) screen_load();\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       p_ptr->window |= (PW_SPELL);\r
+       handle_stuff();\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("激しい戦いの歌を歌った...", "You start singing a song of intense fighting..."));\r
+       /* Abort if needed */\r
+       if (!flag) return FALSE;\r
 \r
-                       (void)hp_player(10);\r
-                       (void)set_afraid(0);\r
+       /* Save the choice */\r
+       (*sn) = spell;\r
 \r
-                       /* Recalculate hitpoints */\r
-                       p_ptr->update |= (PU_HP);\r
+       repeat_push((COMMAND_CODE)spell);\r
 \r
-                       start_singing(spell, MUSIC_HERO);\r
-               }\r
+       /* Success */\r
+       return TRUE;\r
+}\r
 \r
-               if (stop)\r
-               {\r
-                       if (!p_ptr->hero)\r
-                       {\r
-                               msg_print(_("ヒーローの気分が消え失せた。", "The heroism wears off."));\r
-                               /* Recalculate hitpoints */\r
-                               p_ptr->update |= (PU_HP);\r
-                       }\r
-               }\r
+/*!\r
+ * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス\r
+ * @param browse_only 魔法と技能の閲覧を行うならばTRUE\r
+ * @return 魔道書を一冊も持っていないならTRUEを返す\r
+ */\r
+static void confirm_use_force(bool browse_only)\r
+{\r
+       char which;\r
+       COMMAND_CODE code;\r
 \r
-               break;\r
+       /* Get the item index */\r
+       if (repeat_pull(&code) && (code == INVEN_FORCE))\r
+       {\r
+               browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
+               return;\r
+       }\r
 \r
-       case 8:\r
-               if (name) return _("霊的知覚", "Clairaudience");\r
-               if (desc) return _("近くの罠/扉/階段を感知する。レベル15で全てのモンスター、20で財宝とアイテムを感知できるようになる。レベル25で周辺の地形を感知し、40でその階全体を永久に照らし、ダンジョン内のすべてのアイテムを感知する。この効果は歌い続けることで順に起こる。", \r
-                       "Detects traps, doors and stairs in your vicinity. And detects all monsters at level 15, treasures and items at level 20. Maps nearby area at level 25. Lights and know the whole level at level 40. These effects occurs by turns while this song continues.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       /* Show the prompt */\r
+       prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0);\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("静かな音楽が感覚を研ぎ澄まさせた...", "Your quiet music sharpens your sense of hearing..."));\r
-                       /* Hack -- Initialize the turn count */\r
-                       SINGING_COUNT(p_ptr) = 0;\r
-                       start_singing(spell, MUSIC_DETECT);\r
-               }\r
+       while (1)\r
+       {\r
+               /* Get a key */\r
+               which = inkey();\r
 \r
+               if (which == ESCAPE) break;\r
+               else if (which == 'w')\r
                {\r
-                       int rad = DETECT_RAD_DEFAULT;\r
+                       repeat_push(INVEN_FORCE);\r
+                       break;\r
+               }\r
+       }\r
 \r
-                       if (info) return info_radius(rad);\r
+       /* Clear the prompt line */\r
+       prt("", 0, 0);\r
 \r
-                       if (cont)\r
-                       {\r
-                               int count = SINGING_COUNT(p_ptr);\r
+       if (which == 'w')\r
+       {\r
+               browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
+       }\r
+}\r
 \r
-                               if (count >= 19) wiz_lite(FALSE);\r
-                               if (count >= 11)\r
-                               {\r
-                                       map_area(rad);\r
-                                       if (plev > 39 && count < 19)\r
-                                               SINGING_COUNT(p_ptr) = count + 1;\r
-                               }\r
-                               if (count >= 6)\r
-                               {\r
-                                       /* There are too many hidden treasure.  So... */\r
-                                       /* detect_treasure(rad); */\r
-                                       detect_objects_gold(rad);\r
-                                       detect_objects_normal(rad);\r
 \r
-                                       if (plev > 24 && count < 11)\r
-                                               SINGING_COUNT(p_ptr) = count + 1;\r
-                               }\r
-                               if (count >= 3)\r
-                               {\r
-                                       detect_monsters_invis(rad);\r
-                                       detect_monsters_normal(rad);\r
+/*!\r
+ * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン /\r
+ * Peruse the spells/prayers in a book\r
+ * @return なし\r
+ * @details\r
+ * <pre>\r
+ * Note that *all* spells in the book are listed\r
+ *\r
+ * Note that browsing is allowed while confused or blind,\r
+ * and in the dark, primarily to allow browsing in stores.\r
+ * </pre>\r
+ */\r
+void do_cmd_browse(void)\r
+{\r
+       OBJECT_IDX item;\r
+       OBJECT_SUBTYPE_VALUE sval;\r
+       REALM_IDX use_realm = 0;\r
+       int j, line;\r
+       SPELL_IDX spell = -1;\r
+       int num = 0;\r
 \r
-                                       if (plev > 19 && count < 6)\r
-                                               SINGING_COUNT(p_ptr) = count + 1;\r
-                               }\r
-                               detect_traps(rad, TRUE);\r
-                               detect_doors(rad);\r
-                               detect_stairs(rad);\r
+       SPELL_IDX spells[64];\r
+       char temp[62 * 4];\r
 \r
-                               if (plev > 14 && count < 3)\r
-                                       SINGING_COUNT(p_ptr) = count + 1;\r
-                       }\r
-               }\r
+       object_type *o_ptr;\r
 \r
-               break;\r
+       concptr q, s;\r
 \r
-       case 9:\r
-               if (name) return _("魂の歌", "Soul Shriek");\r
-               if (desc) return _("視界内の全てのモンスターに対して精神攻撃を行う。", "Damages all monsters in sight with PSI damages.");\r
+       /* Warriors are illiterate */\r
+       if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
+       {\r
+               msg_print(_("本を読むことができない!", "You cannot read books!"));\r
+               return;\r
+       }\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       if (p_ptr->special_defense & KATA_MUSOU)\r
+       {\r
+               set_action(ACTION_NONE);\r
+       }\r
 \r
-               if (cast)\r
+       if (p_ptr->pclass == CLASS_FORCETRAINER)\r
+       {\r
+               if (player_has_no_spellbooks())\r
                {\r
-                       msg_print(_("精神を捻じ曲げる歌を歌った...", "You start singing a song of soul in pain..."));\r
-                       start_singing(spell, MUSIC_PSI);\r
+                       confirm_use_force(TRUE);\r
+                       return;\r
                }\r
+       }\r
 \r
-               {\r
-                       int dice = 1;\r
-                       int sides = plev * 3 / 2;\r
+       /* Restrict choices to "useful" books */\r
+       if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
+       else item_tester_hook = item_tester_learn_spell;\r
 \r
-                       if (info) return info_damage(dice, sides, 0);\r
+       q = _("どの本を読みますか? ", "Browse which book? ");\r
+       s = _("読める本がない。", "You have no books that you can read.");\r
 \r
-                       if (cont)\r
-                       {\r
-                               project_hack(GF_PSI, damroll(dice, sides));\r
-                       }\r
+       o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
+       if (!o_ptr)\r
+       {\r
+               if (item == INVEN_FORCE) /* the_force */\r
+               {\r
+                       do_cmd_mind_browse();\r
+                       return;\r
                }\r
+               return;\r
+       }\r
 \r
-               break;\r
+       /* Access the item's sval */\r
+       sval = o_ptr->sval;\r
+\r
+       use_realm = tval2realm(o_ptr->tval);\r
 \r
-       case 10:\r
-               if (name) return _("知識の歌", "Song of Lore");\r
-               if (desc) return _("自分のいるマスと隣りのマスに落ちているアイテムを鑑定する。", "Identifies all items which are in the adjacent squares.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       /* Track the object kind */\r
+       object_kind_track(o_ptr->k_idx);\r
+       handle_stuff();\r
 \r
-               if (cast)\r
+       /* Extract spells */\r
+       for (spell = 0; spell < 32; spell++)\r
+       {\r
+               /* Check for this spell */\r
+               if ((fake_spell_flags[sval] & (1L << spell)))\r
                {\r
-                       msg_print(_("この世界の知識が流れ込んできた...", "You recall the rich lore of the world..."));\r
-                       start_singing(spell, MUSIC_ID);\r
+                       /* Collect this spell */\r
+                       spells[num++] = spell;\r
                }\r
+       }\r
 \r
+       screen_save();\r
+       prt("", 0, 0);\r
+\r
+       /* Keep browsing spells.  Exit browsing on cancel. */\r
+       while (TRUE)\r
+       {\r
+               /* Ask for a spell, allow cancel */\r
+               if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm))\r
                {\r
-                       int rad = 1;\r
+                       /* If cancelled, leave immediately. */\r
+                       if (spell == -1) break;\r
 \r
-                       if (info) return info_radius(rad);\r
+                       /* Display a list of spells */\r
+                       print_spells(0, spells, num, 1, 15, use_realm);\r
 \r
-                       /*\r
-                        * 歌の開始時にも効果発動:\r
-                        * MP不足で鑑定が発動される前に歌が中断してしまうのを防止。\r
-                        */\r
-                       if (cont || cast)\r
-                       {\r
-                               project(0, rad, p_ptr->y, p_ptr->x, 0, GF_IDENTIFY, PROJECT_ITEM, -1);\r
-                       }\r
-               }\r
+                       /* Notify that there's nothing to see, and wait. */\r
+                       if (use_realm == REALM_HISSATSU)\r
+                               prt(_("読める技がない。", "No techniques to browse."), 0, 0);\r
+                       else\r
+                               prt(_("読める呪文がない。", "No spells to browse."), 0, 0);\r
+                       (void)inkey();\r
 \r
-               break;\r
+                       screen_load();\r
 \r
-       case 11:\r
-               if (name) return _("隠遁の歌", "Hiding Tune");\r
-               if (desc) return _("隠密行動能力を上昇させる。", "Gives improved stealth.");\r
+                       return;\r
+               }\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+               /* Clear lines, position cursor  (really should use strlen here) */\r
+               Term_erase(14, 14, 255);\r
+               Term_erase(14, 13, 255);\r
+               Term_erase(14, 12, 255);\r
+               Term_erase(14, 11, 255);\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("あなたの姿が景色にとけこんでいった...", "Your song carries you beyond the sight of mortal eyes..."));\r
-                       start_singing(spell, MUSIC_STEALTH);\r
-               }\r
+               roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp));\r
 \r
-               if (stop)\r
+               for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j]))\r
                {\r
-                       if (!p_ptr->tim_stealth)\r
-                       {\r
-                               msg_print(_("姿がはっきりと見えるようになった。", "You are no longer hided."));\r
-                       }\r
+                       prt(&temp[j], line, 15);\r
+                       line++;\r
                }\r
+       }\r
+       screen_load();\r
+}\r
 \r
-               break;\r
+/*!\r
+ * @brief プレイヤーの第二魔法領域を変更する /\r
+ * @param next_realm 変更先の魔法領域ID\r
+ * @return なし\r
+ */\r
+static void change_realm2(CHARACTER_IDX next_realm)\r
+{\r
+       int i, j = 0;\r
+       char tmp[80];\r
 \r
-       case 12:\r
-               if (name) return _("幻影の旋律", "Illusion Pattern");\r
-               if (desc) return _("視界内の全てのモンスターを混乱させる。抵抗されると無効。", "Attempts to confuse all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       for (i = 0; i < 64; i++)\r
+       {\r
+               p_ptr->spell_order[j] = p_ptr->spell_order[i];\r
+               if (p_ptr->spell_order[i] < 32) j++;\r
+       }\r
+       for (; j < 64; j++)\r
+               p_ptr->spell_order[j] = 99;\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("辺り一面に幻影が現れた...", "You weave a pattern of sounds to beguile and confuse..."));\r
-                       start_singing(spell, MUSIC_CONF);\r
-               }\r
+       for (i = 32; i < 64; i++)\r
+       {\r
+               p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;\r
+       }\r
+       p_ptr->spell_learned2 = 0L;\r
+       p_ptr->spell_worked2 = 0L;\r
+       p_ptr->spell_forgotten2 = 0L;\r
 \r
-               {\r
-                       int power = plev * 2;\r
+       sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]);\r
+       do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);\r
+       p_ptr->old_realm |= 1 << (p_ptr->realm2 - 1);\r
+       p_ptr->realm2 = next_realm;\r
 \r
-                       if (info) return info_power(power);\r
+       p_ptr->update |= (PU_REORDER);\r
+       p_ptr->update |= (PU_SPELLS);\r
+       handle_stuff();\r
 \r
-                       if (cont)\r
-                       {\r
-                               confuse_monsters(power);\r
-                       }\r
-               }\r
+       /* Load an autopick preference file */\r
+       autopick_load_pref(FALSE);\r
+}\r
 \r
-               break;\r
 \r
-       case 13:\r
-               if (name) return _("破滅の叫び", "Doomcall");\r
-               if (desc) return _("視界内の全てのモンスターに対して轟音攻撃を行う。", "Damages all monsters in sight with booming sound.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+/*!\r
+ * @brief 魔法を学習するコマンドのメインルーチン /\r
+ * Study a book to gain a new spell/prayer\r
+ * @return なし\r
+ */\r
+void do_cmd_study(void)\r
+{\r
+       int     i;\r
+       OBJECT_IDX item;\r
+       OBJECT_SUBTYPE_VALUE sval;\r
+       int     increment = 0;\r
+       bool    learned = FALSE;\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("轟音が響いた...", "The fury of the Downfall of Numenor lashes out..."));\r
-                       start_singing(spell, MUSIC_SOUND);\r
-               }\r
+       /* Spells of realm2 will have an increment of +32 */\r
+       SPELL_IDX spell = -1;\r
 \r
-               {\r
-                       int dice = 10 + plev / 5;\r
-                       int sides = 7;\r
+       concptr p = spell_category_name(mp_ptr->spell_book);\r
 \r
-                       if (info) return info_damage(dice, sides, 0);\r
+       object_type *o_ptr;\r
 \r
-                       if (cont)\r
-                       {\r
-                               project_hack(GF_SOUND, damroll(dice, sides));\r
-                       }\r
-               }\r
+       concptr q, s;\r
 \r
-               break;\r
+       if (!p_ptr->realm1)\r
+       {\r
+               msg_print(_("本を読むことができない!", "You cannot read books!"));\r
+               return;\r
+       }\r
 \r
-       case 14:\r
-               if (name) return _("フィリエルの歌", "Firiel's Song");\r
-               if (desc) return _("周囲の死体や骨を生き返す。", "Resurrects nearby corpse and skeletons. And makes these your pets.");\r
-    \r
-               {\r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
+       if (p_ptr->blind || no_lite())\r
+       {\r
+               msg_print(_("目が見えない!", "You cannot see!"));\r
+               return;\r
+       }\r
 \r
-                       if (cast)\r
-                       {\r
-                               msg_print(_("生命と復活のテーマを奏で始めた...", "The themes of life and revival are woven into your song..."));\r
-                               animate_dead(0, p_ptr->y, p_ptr->x);\r
-                       }\r
-               }\r
-               break;\r
+       if (cmd_limit_confused(p_ptr)) return;\r
 \r
-       case 15:\r
-               if (name) return _("旅の仲間", "Fellowship Chant");\r
-               if (desc) return _("視界内の全てのモンスターを魅了する。抵抗されると無効。", "Attempts to charm all monsters in sight.");\r
+       if (!(p_ptr->new_spells))\r
+       {\r
+               msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);\r
+               return;\r
+       }\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       if (p_ptr->special_defense & KATA_MUSOU)\r
+       {\r
+               set_action(ACTION_NONE);\r
+       }\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("安らかなメロディを奏で始めた...", "You weave a slow, soothing melody of imploration..."));\r
-                       start_singing(spell, MUSIC_CHARM);\r
-               }\r
+#ifdef JP\r
+       if (p_ptr->new_spells < 10) {\r
+               msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);\r
+       }\r
+       else {\r
+               msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);\r
+       }\r
+#else\r
+       msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,\r
+               (p_ptr->new_spells == 1 ? "" : "s"));\r
+#endif\r
 \r
-               {\r
-                       int dice = 10 + plev / 15;\r
-                       int sides = 6;\r
+       msg_print(NULL);\r
 \r
-                       if (info) return info_power_dice(dice, sides);\r
 \r
-                       if (cont)\r
-                       {\r
-                               charm_monsters(damroll(dice, sides));\r
-                       }\r
-               }\r
+       /* Restrict choices to "useful" books */\r
+       if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
+       else item_tester_hook = item_tester_learn_spell;\r
 \r
-               break;\r
+       q = _("どの本から学びますか? ", "Study which book? ");\r
+       s = _("読める本がない。", "You have no books that you can read.");\r
 \r
-       case 16:\r
-               if (name) return _("分解音波", "Sound of disintegration");\r
-               if (desc) return _("壁を掘り進む。自分の足元のアイテムは蒸発する。", "Makes you be able to burrow into walls. Objects under your feet evaporate.");\r
+       o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
+       if (!o_ptr) return;\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       /* Access the item's sval */\r
+       sval = o_ptr->sval;\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("粉砕するメロディを奏で始めた...", "You weave a violent pattern of sounds to break wall."));\r
-                       start_singing(spell, MUSIC_WALL);\r
-               }\r
+       if (o_ptr->tval == REALM2_BOOK) increment = 32;\r
+       else if (o_ptr->tval != REALM1_BOOK)\r
+       {\r
+               if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;\r
+               change_realm2(tval2realm(o_ptr->tval));\r
+               increment = 32;\r
+       }\r
 \r
-               {\r
-                       /*\r
-                        * 歌の開始時にも効果発動:\r
-                        * MP不足で効果が発動される前に歌が中断してしまうのを防止。\r
-                        */\r
-                       if (cont || cast)\r
-                       {\r
-                               project(0, 0, p_ptr->y, p_ptr->x,\r
-                                       0, GF_DISINTEGRATE, PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE, -1);\r
-                       }\r
-               }\r
-               break;\r
+       /* Track the object kind */\r
+       object_kind_track(o_ptr->k_idx);\r
+       handle_stuff();\r
 \r
-       case 17:\r
-               if (name) return _("元素耐性", "Finrod's Resistance");\r
-               if (desc) return _("酸、電撃、炎、冷気、毒に対する耐性を得る。装備による耐性に累積する。", \r
-                       "Gives resistance to fire, cold, electricity, acid and poison. These resistances can be added to which from equipment for more powerful resistances.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       /* Mage -- Learn a selected spell */\r
+       if (mp_ptr->spell_book != TV_LIFE_BOOK)\r
+       {\r
+               /* Ask for a spell, allow cancel */\r
+               if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;\r
+       }\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("元素の力に対する忍耐の歌を歌った。", "You sing a song of perseverance against powers..."));\r
-                       start_singing(spell, MUSIC_RESIST);\r
-               }\r
+       /* Priest -- Learn a random prayer */\r
+       else\r
+       {\r
+               int k = 0;\r
+               int gift = -1;\r
 \r
-               if (stop)\r
+               /* Extract spells */\r
+               for (spell = 0; spell < 32; spell++)\r
                {\r
-                       if (!p_ptr->oppose_acid)\r
+                       /* Check spells in the book */\r
+                       if ((fake_spell_flags[sval] & (1L << spell)))\r
                        {\r
-                               msg_print(_("酸への耐性が薄れた気がする。", "You feel less resistant to acid."));\r
-                       }\r
+                               /* Skip non "okay" prayers */\r
+                               if (!spell_okay(spell, FALSE, TRUE,\r
+                                       (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;\r
 \r
-                       if (!p_ptr->oppose_elec)\r
-                       {\r
-                               msg_print(_("電撃への耐性が薄れた気がする。", "You feel less resistant to elec."));\r
-                       }\r
+                               /* Hack -- Prepare the randomizer */\r
+                               k++;\r
 \r
-                       if (!p_ptr->oppose_fire)\r
-                       {\r
-                               msg_print(_("火への耐性が薄れた気がする。", "You feel less resistant to fire."));\r
+                               /* Hack -- Apply the randomizer */\r
+                               if (one_in_(k)) gift = spell;\r
                        }\r
+               }\r
 \r
-                       if (!p_ptr->oppose_cold)\r
-                       {\r
-                               msg_print(_("冷気への耐性が薄れた気がする。", "You feel less resistant to cold."));\r
-                       }\r
+               /* Accept gift */\r
+               spell = gift;\r
+       }\r
 \r
-                       if (!p_ptr->oppose_pois)\r
-                       {\r
-                               msg_print(_("毒への耐性が薄れた気がする。", "You feel less resistant to pois."));\r
-                       }\r
-               }\r
+       /* Nothing to study */\r
+       if (spell < 0)\r
+       {\r
+               msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);\r
 \r
-               break;\r
+               /* Abort */\r
+               return;\r
+       }\r
 \r
-       case 18:\r
-               if (name) return _("ホビットのメロディ", "Hobbit Melodies");\r
-               if (desc) return _("加速する。", "Hastes you.");\r
+       if (increment) spell += increment;\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       /* Learn the spell */\r
+       if (spell < 32)\r
+       {\r
+               if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;\r
+               else p_ptr->spell_learned1 |= (1L << spell);\r
+       }\r
+       else\r
+       {\r
+               if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;\r
+               else p_ptr->spell_learned2 |= (1L << (spell - 32));\r
+       }\r
+\r
+       if (learned)\r
+       {\r
+               int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;\r
+               int old_exp = p_ptr->spell_exp[spell];\r
+               int new_rank = EXP_LEVEL_UNSKILLED;\r
+               concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME);\r
 \r
-               if (cast)\r
+               if (old_exp >= max_exp)\r
                {\r
-                       msg_print(_("軽快な歌を口ずさみ始めた...", "You start singing joyful pop song..."));\r
-                       start_singing(spell, MUSIC_SPEED);\r
+                       msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);\r
+                       return;\r
                }\r
-\r
-               if (stop)\r
+#ifdef JP\r
+               if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))\r
+#else\r
+               if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))\r
+#endif\r
                {\r
-                       if (!p_ptr->fast)\r
-                       {\r
-                               msg_print(_("動きの素早さがなくなったようだ。", "You feel yourself slow down."));\r
-                       }\r
+                       return;\r
                }\r
-\r
-               break;\r
-\r
-       case 19:\r
-               if (name) return _("歪んだ世界", "World Contortion");\r
-               if (desc) return _("近くのモンスターをテレポートさせる。抵抗されると無効。", "Teleports all nearby monsters away unless resisted.");\r
-    \r
+               else if (old_exp >= SPELL_EXP_EXPERT)\r
                {\r
-                       int rad = plev / 15 + 1;\r
-                       int power = plev * 3 + 1;\r
-\r
-                       if (info) return info_radius(rad);\r
-\r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
-\r
-                       if (cast)\r
-                       {\r
-                               msg_print(_("歌が空間を歪めた...", "Reality whirls wildly as you sing a dizzying melody..."));\r
-                               project(0, rad, p_ptr->y, p_ptr->x, power, GF_AWAY_ALL, PROJECT_KILL, -1);\r
-                       }\r
+                       p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;\r
+                       new_rank = EXP_LEVEL_MASTER;\r
                }\r
-               break;\r
-\r
-       case 20:\r
-               if (name) return _("退散の歌", "Dispelling chant");\r
-               if (desc) return _("視界内の全てのモンスターにダメージを与える。邪悪なモンスターに特に大きなダメージを与える。", \r
-                       "Damages all monsters in sight. Hurts evil monsters greatly.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
-\r
-               if (cast)\r
+               else if (old_exp >= SPELL_EXP_SKILLED)\r
                {\r
-                       msg_print(_("耐えられない不協和音が敵を責め立てた...", "You cry out in an ear-wracking voice..."));\r
-                       start_singing(spell, MUSIC_DISPEL);\r
+                       if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;\r
+                       else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;\r
+                       new_rank = EXP_LEVEL_EXPERT;\r
                }\r
-\r
+               else if (old_exp >= SPELL_EXP_BEGINNER)\r
                {\r
-                       int m_sides = plev * 3;\r
-                       int e_sides = plev * 3;\r
-\r
-                       if (info) return format("%s1d%d+1d%d", s_dam, m_sides, e_sides);\r
-\r
-                       if (cont)\r
-                       {\r
-                               dispel_monsters(randint1(m_sides));\r
-                               dispel_evil(randint1(e_sides));\r
-                       }\r
+                       p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;\r
+                       new_rank = EXP_LEVEL_SKILLED;\r
                }\r
-               break;\r
-\r
-       case 21:\r
-               if (name) return _("サルマンの甘言", "The Voice of Saruman");\r
-               if (desc) return _("視界内の全てのモンスターを減速させ、眠らせようとする。抵抗されると無効。", "Attempts to slow and sleep all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
-\r
-               if (cast)\r
+               else\r
                {\r
-                       msg_print(_("優しく、魅力的な歌を口ずさみ始めた...", "You start humming a gentle and attractive song..."));\r
-                       start_singing(spell, MUSIC_SARUMAN);\r
+                       p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;\r
+                       new_rank = EXP_LEVEL_BEGINNER;\r
                }\r
-\r
+               msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);\r
+       }\r
+       else\r
+       {\r
+               /* Find the next open entry in "p_ptr->spell_order[]" */\r
+               for (i = 0; i < 64; i++)\r
                {\r
-                       int power = plev;\r
-\r
-                       if (info) return info_power(power);\r
-\r
-                       if (cont)\r
-                       {\r
-                               slow_monsters(plev);\r
-                               sleep_monsters(plev);\r
-                       }\r
+                       /* Stop at the first empty space */\r
+                       if (p_ptr->spell_order[i] == 99) break;\r
                }\r
 \r
-               break;\r
+               /* Add the spell to the known list */\r
+               p_ptr->spell_order[i++] = spell;\r
 \r
-       case 22:\r
-               if (name) return _("嵐の音色", "Song of the Tempest");\r
-               if (desc) return _("轟音のビームを放つ。", "Fires a beam of sound.");\r
-    \r
+               /* Mention the result */\r
+#ifdef JP\r
+               /* 英日切り替え機能に対応 */\r
+               if (mp_ptr->spell_book == TV_MUSIC_BOOK)\r
                {\r
-                       int dice = 15 + (plev - 1) / 2;\r
-                       int sides = 10;\r
-\r
-                       if (info) return info_damage(dice, sides, 0);\r
-\r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
+                       msg_format("%sを学んだ。",\r
+                               do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
+               }\r
+               else\r
+               {\r
+                       msg_format("%sの%sを学んだ。",\r
+                               do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p);\r
+               }\r
+#else\r
+               msg_format("You have learned the %s of %s.",\r
+                       p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
+#endif\r
+       }\r
 \r
-                       if (cast)\r
-                       {\r
-                               if (!get_aim_dir(&dir)) return NULL;\r
+       p_ptr->energy_use = 100;\r
 \r
-                               fire_beam(GF_SOUND, dir, damroll(dice, sides));\r
-                       }\r
-               }\r
+       switch (mp_ptr->spell_book)\r
+       {\r
+       case TV_LIFE_BOOK:\r
+               chg_virtue(V_FAITH, 1);\r
+               break;\r
+       case TV_DEATH_BOOK:\r
+               chg_virtue(V_UNLIFE, 1);\r
+               break;\r
+       case TV_NATURE_BOOK:\r
+               chg_virtue(V_NATURE, 1);\r
                break;\r
+       default:\r
+               chg_virtue(V_KNOWLEDGE, 1);\r
+               break;\r
+       }\r
 \r
-       case 23:\r
-               if (name) return _("もう一つの世界", "Ambarkanta");\r
-               if (desc) return _("現在の階を再構成する。", "Recreates current dungeon level.");\r
-    \r
-               {\r
-                       int base = 15;\r
-                       int sides = 20;\r
+       sound(SOUND_STUDY);\r
 \r
-                       if (info) return info_delay(base, sides);\r
+       /* One less spell available */\r
+       p_ptr->learned_spells++;\r
 \r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
+       /* Update Study */\r
+       p_ptr->update |= (PU_SPELLS);\r
+       update_creature(p_ptr);\r
 \r
-                       if (cast)\r
-                       {\r
-                               msg_print(_("周囲が変化し始めた...", "You sing of the primeval shaping of Middle-earth..."));\r
-                               alter_reality();\r
-                       }\r
-               }\r
-               break;\r
+       /* Redraw object recall */\r
+       p_ptr->window |= (PW_OBJECT);\r
+}\r
 \r
-       case 24:\r
-               if (name) return _("破壊の旋律", "Wrecking Pattern");\r
-               if (desc) return _("周囲のダンジョンを揺らし、壁と床をランダムに入れ変える。", \r
-                       "Shakes dungeon structure, and results in random swapping of floors and walls.");\r
 \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+/*!\r
+ * @brief 魔法を詠唱するコマンドのメインルーチン /\r
+ * Cast a spell\r
+ * @return なし\r
+ */\r
+void do_cmd_cast(void)\r
+{\r
+       OBJECT_IDX item;\r
+       OBJECT_SUBTYPE_VALUE sval;\r
+       SPELL_IDX spell;\r
+       REALM_IDX realm;\r
+       int     chance;\r
+       int     increment = 0;\r
+       REALM_IDX use_realm;\r
+       MANA_POINT need_mana;\r
+\r
+       concptr prayer;\r
+       object_type *o_ptr;\r
+       const magic_type *s_ptr;\r
+       concptr q, s;\r
+\r
+       bool over_exerted = FALSE;\r
+\r
+       /* Require spell ability */\r
+       if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
+       {\r
+               msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));\r
+               return;\r
+       }\r
 \r
-               if (cast)\r
+       /* Require lite */\r
+       if (p_ptr->blind || no_lite())\r
+       {\r
+               if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);\r
+               else\r
                {\r
-                       msg_print(_("ç ´å£\8aç\9a\84ã\81ªæ­\8cã\81\8cé\9f¿ã\81\8dã\82\8fã\81\9fã\81£ã\81\9fï¼\8eï¼\8eï¼\8e", "You weave a pattern of sounds to contort and shatter..."));\r
-                       start_singing(spell, MUSIC_QUAKE);\r
+                       msg_print(_("ç\9b®ã\81\8cè¦\8bã\81\88ã\81ªã\81\84ï¼\81", "You cannot see!"));\r
+                       flush();\r
                }\r
+               return;\r
+       }\r
 \r
-               {\r
-                       int rad = 10;\r
+       if (cmd_limit_confused(p_ptr)) return;\r
 \r
-                       if (info) return info_radius(rad);\r
+       /* Hex */\r
+       if (p_ptr->realm1 == REALM_HEX)\r
+       {\r
+               if (hex_spell_fully())\r
+               {\r
+                       bool flag = FALSE;\r
+                       msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));\r
+                       flush();\r
+                       if (p_ptr->lev >= 35) flag = stop_hex_spell();\r
+                       if (!flag) return;\r
+               }\r
+       }\r
 \r
-                       if (cont)\r
-                       {\r
-                               earthquake(p_ptr->y, p_ptr->x, 10);\r
-                       }\r
+       if (p_ptr->pclass == CLASS_FORCETRAINER)\r
+       {\r
+               if (player_has_no_spellbooks())\r
+               {\r
+                       confirm_use_force(FALSE);\r
+                       return;\r
                }\r
+       }\r
 \r
-               break;\r
+       prayer = spell_category_name(mp_ptr->spell_book);\r
 \r
+       /* Restrict choices to spell books */\r
+       item_tester_tval = mp_ptr->spell_book;\r
 \r
-       case 25:\r
-               if (name) return _("停滞の歌", "Stationary Shriek");\r
-               if (desc) return _("視界内の全てのモンスターを麻痺させようとする。抵抗されると無効。", "Attempts to freeze all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       q = _("どの呪文書を使いますか? ", "Use which book? ");\r
+       s = _("呪文書がない!", "You have no spell books!");\r
 \r
-               if (cast)\r
+       o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
+       if (!o_ptr)\r
+       {\r
+               if (item == INVEN_FORCE) /* the_force */\r
                {\r
-                       msg_print(_("ゆっくりとしたメロディを奏で始めた...", "You weave a very slow pattern which is almost likely to stop..."));\r
-                       start_singing(spell, MUSIC_STASIS);\r
+                       do_cmd_mind();\r
+                       return;\r
                }\r
+               return;\r
+       }\r
 \r
-               {\r
-                       int power = plev * 4;\r
+       /* Access the item's sval */\r
+       sval = o_ptr->sval;\r
 \r
-                       if (info) return info_power(power);\r
+       if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;\r
 \r
-                       if (cont)\r
-                       {\r
-                               stasis_monsters(power);\r
-                       }\r
-               }\r
+       /* Track the object kind */\r
+       object_kind_track(o_ptr->k_idx);\r
+       handle_stuff();\r
 \r
-               break;\r
+       if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))\r
+               realm = o_ptr->tval - TV_LIFE_BOOK + 1;\r
+       else if (increment) realm = p_ptr->realm2;\r
+       else realm = p_ptr->realm1;\r
 \r
-       case 26:\r
-               if (name) return _("守りの歌", "Endurance");\r
-               if (desc) return _("自分のいる床の上に、モンスターが通り抜けたり召喚されたりすることができなくなるルーンを描く。", \r
-                       "Sets a glyph on the floor beneath you. Monsters cannot attack you if you are on a glyph, but can try to break glyph.");\r
-    \r
-               {\r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
+       /* Ask for a spell */\r
+#ifdef JP\r
+       if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),\r
+               sval, TRUE, realm))\r
+       {\r
+               if (spell == -2) msg_format("その本には知っている%sがない。", prayer);\r
+               return;\r
+       }\r
+#else\r
+       if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
+               sval, TRUE, realm))\r
+       {\r
+               if (spell == -2)\r
+                       msg_format("You don't know any %ss in that book.", prayer);\r
+               return;\r
+       }\r
+#endif\r
 \r
-                       if (cast)\r
-                       {\r
-                               msg_print(_("歌が神聖な場を作り出した...", "The holy power of the Music is creating sacred field..."));\r
-                               warding_glyph();\r
-                       }\r
-               }\r
-               break;\r
 \r
-       case 27:\r
-               if (name) return _("英雄の詩", "The Hero's Poem");\r
-               if (desc) return _("加速し、ヒーロー気分になり、視界内の全てのモンスターにダメージを与える。", \r
-                       "Hastes you. Gives heroism. Damages all monsters in sight.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+       use_realm = tval2realm(o_ptr->tval);\r
 \r
-               if (cast)\r
+       /* Hex */\r
+       if (use_realm == REALM_HEX)\r
+       {\r
+               if (hex_spelling(spell))\r
                {\r
-                       msg_print(_("英雄の歌を口ずさんだ...", "You chant a powerful, heroic call to arms..."));\r
-                       (void)hp_player(10);\r
-                       (void)set_afraid(0);\r
-\r
-                       /* Recalculate hitpoints */\r
-                       p_ptr->update |= (PU_HP);\r
-\r
-                       start_singing(spell, MUSIC_SHERO);\r
+                       msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));\r
+                       return;\r
                }\r
+       }\r
 \r
-               if (stop)\r
-               {\r
-                       if (!p_ptr->hero)\r
-                       {\r
-                               msg_print(_("ヒーローの気分が消え失せた。", "The heroism wears off."));\r
-                               /* Recalculate hitpoints */\r
-                               p_ptr->update |= (PU_HP);\r
-                       }\r
+       if (!is_magic(use_realm))\r
+       {\r
+               s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
+       }\r
+       else\r
+       {\r
+               s_ptr = &mp_ptr->info[realm - 1][spell];\r
+       }\r
 \r
-                       if (!p_ptr->fast)\r
-                       {\r
-                               msg_print(_("動きの素早さがなくなったようだ。", "You feel yourself slow down."));\r
-                       }\r
-               }\r
+       /* Extract mana consumption rate */\r
+       need_mana = mod_need_mana(s_ptr->smana, spell, realm);\r
 \r
-               {\r
-                       int dice = 1;\r
-                       int sides = plev * 3;\r
+       /* Verify "dangerous" spells */\r
+       if (need_mana > p_ptr->csp)\r
+       {\r
+               if (flush_failure) flush();\r
 \r
-                       if (info) return info_damage(dice, sides, 0);\r
+               /* Warning */\r
+#ifdef JP\r
+               msg_format("その%sを%sのに十分なマジックポイントがない。", prayer,\r
+                       ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));\r
+#else\r
+               msg_format("You do not have enough mana to %s this %s.",\r
+                       ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
+                       prayer);\r
+#endif\r
 \r
-                       if (cont)\r
-                       {\r
-                               dispel_monsters(damroll(dice, sides));\r
-                       }\r
-               }\r
-               break;\r
 \r
-       case 28:\r
-               if (name) return _("ヤヴァンナの助け", "Relief of Yavanna");\r
-               if (desc) return _("強力な回復の歌で、負傷と朦朧状態も全快する。", "Powerful healing song. Also heals cut and stun completely.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
+               if (!over_exert) return;\r
 \r
-               if (cast)\r
-               {\r
-                       msg_print(_("歌を通して体に活気が戻ってきた...", "Life flows through you as you sing the song..."));\r
-                       start_singing(spell, MUSIC_H_LIFE);\r
-               }\r
+               /* Verify */\r
+               if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;\r
+       }\r
 \r
-               {\r
-                       int dice = 15;\r
-                       int sides = 10;\r
+       /* Spell failure chance */\r
+       chance = spell_chance(spell, use_realm);\r
 \r
-                       if (info) return info_heal(dice, sides, 0);\r
+       /* Sufficient mana */\r
+       if (need_mana <= p_ptr->csp)\r
+       {\r
+               /* Use some mana */\r
+               p_ptr->csp -= need_mana;\r
+       }\r
+       else over_exerted = TRUE;\r
+       p_ptr->redraw |= (PR_MANA);\r
 \r
-                       if (cont)\r
-                       {\r
-                               hp_player(damroll(dice, sides));\r
-                               set_stun(0);\r
-                               set_cut(0);\r
-                       }\r
-               }\r
+       /* Failed spell */\r
+       if (randint0(100) < chance)\r
+       {\r
+               if (flush_failure) flush();\r
 \r
-               break;\r
+               msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);\r
+               sound(SOUND_FAIL);\r
 \r
-       case 29:\r
-               if (name) return _("再生の歌", "Goddess' rebirth");\r
-               if (desc) return _("すべてのステータスと経験値を回復する。", "Restores all stats and experience.");\r
-    \r
+               switch (realm)\r
                {\r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
-\r
-                       if (cast)\r
-                       {\r
-                               msg_print(_("暗黒の中に光と美をふりまいた。体が元の活力を取り戻した。",\r
-                                                       "You strewed light and beauty in the dark as you sing. You feel refreshed."));\r
-                               (void)do_res_stat(A_STR);\r
-                               (void)do_res_stat(A_INT);\r
-                               (void)do_res_stat(A_WIS);\r
-                               (void)do_res_stat(A_DEX);\r
-                               (void)do_res_stat(A_CON);\r
-                               (void)do_res_stat(A_CHR);\r
-                               (void)restore_level();\r
-                       }\r
+               case REALM_LIFE:\r
+                       if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);\r
+                       break;\r
+               case REALM_DEATH:\r
+                       if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);\r
+                       break;\r
+               case REALM_NATURE:\r
+                       if (randint1(100) < chance) chg_virtue(V_NATURE, -1);\r
+                       break;\r
+               case REALM_DAEMON:\r
+                       if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);\r
+                       break;\r
+               case REALM_CRUSADE:\r
+                       if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);\r
+                       break;\r
+               case REALM_HEX:\r
+                       if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);\r
+                       break;\r
+               default:\r
+                       if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);\r
+                       break;\r
                }\r
-               break;\r
-\r
-       case 30:\r
-               if (name) return _("サウロンの魔術", "Wizardry of Sauron");\r
-               if (desc) return _("非常に強力でごく小さい轟音の球を放つ。", "Fires an extremely powerful tiny ball of sound.");\r
-    \r
-               {\r
-                       int dice = 50 + plev;\r
-                       int sides = 10;\r
-                       int rad = 0;\r
-\r
-                       if (info) return info_damage(dice, sides, 0);\r
 \r
-                       /* Stop singing before start another */\r
-                       if (cast || fail) stop_singing();\r
+               /* Failure casting may activate some side effect */\r
+               do_spell(realm, spell, SPELL_FAIL);\r
 \r
-                       if (cast)\r
-                       {\r
-                               if (!get_aim_dir(&dir)) return NULL;\r
-\r
-                               fire_ball(GF_SOUND, dir, damroll(dice, sides), rad);\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 31:\r
-               if (name) return _("フィンゴルフィンの挑戦", "Fingolfin's Challenge");\r
-               if (desc) return _("ダメージを受けなくなるバリアを張る。", \r
-                       "Generates barrier which completely protect you from almost all damages. Takes a few your turns when the barrier breaks.");\r
-    \r
-               /* Stop singing before start another */\r
-               if (cast || fail) stop_singing();\r
 \r
-               if (cast)\r
+               if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))\r
                {\r
-                       msg_print(_("フィンゴルフィンの冥王への挑戦を歌った...",\r
-                                               "You recall the valor of Fingolfin's challenge to the Dark Lord..."));\r
-\r
-                       /* Redraw map */\r
-                       p_ptr->redraw |= (PR_MAP);\r
-               \r
-                       /* Update monsters */\r
-                       p_ptr->update |= (PU_MONSTERS);\r
-               \r
-                       /* Window stuff */\r
-                       p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);\r
-\r
-                       start_singing(spell, MUSIC_INVULN);\r
+                       msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));\r
+                       wild_magic(spell);\r
                }\r
-\r
-               if (stop)\r
+               else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))\r
                {\r
-                       if (!p_ptr->invuln)\r
+                       if ((sval == 3) && one_in_(2))\r
                        {\r
-                               msg_print(_("無敵ではなくなった。", "The invulnerability wears off."));\r
-                               /* Redraw map */\r
-                               p_ptr->redraw |= (PR_MAP);\r
-\r
-                               /* Update monsters */\r
-                               p_ptr->update |= (PU_MONSTERS);\r
+                               sanity_blast(0, TRUE);\r
+                       }\r
+                       else\r
+                       {\r
+                               msg_print(_("痛い!", "It hurts!"));\r
+                               take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);\r
 \r
-                               /* Window stuff */\r
-                               p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);\r
+                               if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)\r
+                                       lose_exp(spell * 250);\r
                        }\r
                }\r
-\r
-               break;\r
+               else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))\r
+               {\r
+                       msg_print(_("いやな音が響いた", "An infernal sound echoed."));\r
+                       aggravate_monsters(0);\r
+               }\r
+               if (randint1(100) >= chance)\r
+                       chg_virtue(V_CHANCE, -1);\r
        }\r
 \r
-       return "";\r
-}\r
-\r
-/*!\r
- * @brief 剣術の各処理を行う\r
- * @param spell 剣術ID\r
- * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_CAST)\r
- * @return SPELL_NAME / SPELL_DESC 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。\r
- */\r
-static cptr do_hissatsu_spell(SPELL_IDX spell, BIT_FLAGS mode)\r
-{\r
-       bool name = (mode == SPELL_NAME) ? TRUE : FALSE;\r
-       bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;\r
-       bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;\r
-\r
-       int dir;\r
-       int plev = p_ptr->lev;\r
-\r
-       switch (spell)\r
+       /* Process spell */\r
+       else\r
        {\r
-       case 0:\r
-               if (name) return _("飛飯綱", "Tobi-Izuna");\r
-               if (desc) return _("2マス離れたところにいるモンスターを攻撃する。", "Attacks a two squares distant monster.");\r
-    \r
-               if (cast)\r
-               {\r
-                       project_length = 2;\r
-                       if (!get_aim_dir(&dir)) return NULL;\r
+               /* Canceled spells cost neither a turn nor mana */\r
+               if (!do_spell(realm, spell, SPELL_CAST)) return;\r
 \r
-                       project_hook(GF_ATTACK, dir, HISSATSU_2, PROJECT_STOP | PROJECT_KILL);\r
-               }\r
-               break;\r
+               if (randint1(100) < chance)\r
+                       chg_virtue(V_CHANCE, 1);\r
 \r
-       case 1:\r
-               if (name) return _("五月雨斬り", "3-Way Attack");\r
-               if (desc) return _("3方向に対して攻撃する。", "Attacks in 3 directions in one time.");\r
-    \r
-               if (cast)\r
+               /* A spell was cast */\r
+               if (!(increment ?\r
+                       (p_ptr->spell_worked2 & (1L << spell)) :\r
+                       (p_ptr->spell_worked1 & (1L << spell)))\r
+                       && (p_ptr->pclass != CLASS_SORCERER)\r
+                       && (p_ptr->pclass != CLASS_RED_MAGE))\r
                {\r
-                       int cdir;\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
+                       int e = s_ptr->sexp;\r
 \r
-                       for (cdir = 0;cdir < 8; cdir++)\r
+                       /* The spell worked */\r
+                       if (realm == p_ptr->realm1)\r
                        {\r
-                               if (cdd[cdir] == dir) break;\r
+                               p_ptr->spell_worked1 |= (1L << spell);\r
                        }\r
-\r
-                       if (cdir == 8) return NULL;\r
-\r
-                       y = p_ptr->y + ddy_cdd[cdir];\r
-                       x = p_ptr->x + ddx_cdd[cdir];\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, 0);\r
-                       else\r
-                               msg_print(_("攻撃は空を切った。", "You attack the empty air."));\r
-                       \r
-                       y = p_ptr->y + ddy_cdd[(cdir + 7) % 8];\r
-                       x = p_ptr->x + ddx_cdd[(cdir + 7) % 8];\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, 0);\r
-                       else\r
-                               msg_print(_("攻撃は空を切った。", "You attack the empty air."));\r
-                       \r
-                       y = p_ptr->y + ddy_cdd[(cdir + 1) % 8];\r
-                       x = p_ptr->x + ddx_cdd[(cdir + 1) % 8];\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, 0);\r
                        else\r
-                               msg_print(_("攻撃は空を切った。", "You attack the empty air."));\r
-               }\r
-               break;\r
-\r
-       case 2:\r
-               if (name) return _("ブーメラン", "Boomerang");\r
-               if (desc) return _("武器を手元に戻ってくるように投げる。戻ってこないこともある。", \r
-                       "Throws current weapon. And it'll return to your hand unless failed.");\r
-    \r
-               if (cast)\r
-               {\r
-                       if (!do_cmd_throw(1, TRUE, -1)) return NULL;\r
-               }\r
-               break;\r
-\r
-       case 3:\r
-               if (name) return _("焔霊", "Burning Strike");\r
-               if (desc) return _("火炎耐性のないモンスターに大ダメージを与える。", "Attacks a monster with more damage unless it has resistance to fire.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
+                       {\r
+                               p_ptr->spell_worked2 |= (1L << spell);\r
+                       }\r
 \r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
+                       /* Gain experience */\r
+                       gain_exp(e * s_ptr->slevel);\r
 \r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
+                       /* Redraw object recall */\r
+                       p_ptr->window |= (PW_OBJECT);\r
 \r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_FIRE);\r
-                       else\r
+                       switch (realm)\r
                        {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
+                       case REALM_LIFE:\r
+                               chg_virtue(V_TEMPERANCE, 1);\r
+                               chg_virtue(V_COMPASSION, 1);\r
+                               chg_virtue(V_VITALITY, 1);\r
+                               chg_virtue(V_DILIGENCE, 1);\r
+                               break;\r
+                       case REALM_DEATH:\r
+                               chg_virtue(V_UNLIFE, 1);\r
+                               chg_virtue(V_JUSTICE, -1);\r
+                               chg_virtue(V_FAITH, -1);\r
+                               chg_virtue(V_VITALITY, -1);\r
+                               break;\r
+                       case REALM_DAEMON:\r
+                               chg_virtue(V_JUSTICE, -1);\r
+                               chg_virtue(V_FAITH, -1);\r
+                               chg_virtue(V_HONOUR, -1);\r
+                               chg_virtue(V_TEMPERANCE, -1);\r
+                               break;\r
+                       case REALM_CRUSADE:\r
+                               chg_virtue(V_FAITH, 1);\r
+                               chg_virtue(V_JUSTICE, 1);\r
+                               chg_virtue(V_SACRIFICE, 1);\r
+                               chg_virtue(V_HONOUR, 1);\r
+                               break;\r
+                       case REALM_NATURE:\r
+                               chg_virtue(V_NATURE, 1);\r
+                               chg_virtue(V_HARMONY, 1);\r
+                               break;\r
+                       case REALM_HEX:\r
+                               chg_virtue(V_JUSTICE, -1);\r
+                               chg_virtue(V_FAITH, -1);\r
+                               chg_virtue(V_HONOUR, -1);\r
+                               chg_virtue(V_COMPASSION, -1);\r
+                               break;\r
+                       default:\r
+                               chg_virtue(V_KNOWLEDGE, 1);\r
+                               break;\r
                        }\r
                }\r
-               break;\r
-\r
-       case 4:\r
-               if (name) return _("殺気感知", "Detect Ferocity");\r
-               if (desc) return _("近くの思考することができるモンスターを感知する。", "Detects all monsters except mindless in your vicinity.");\r
-    \r
-               if (cast)\r
-               {\r
-                       detect_monsters_mind(DETECT_RAD_DEFAULT);\r
+               switch (realm)\r
+               {\r
+               case REALM_LIFE:\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);\r
+                       break;\r
+               case REALM_DEATH:\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1);\r
+                       break;\r
+               case REALM_DAEMON:\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);\r
+                       break;\r
+               case REALM_CRUSADE:\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);\r
+                       break;\r
+               case REALM_NATURE:\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);\r
+                       break;\r
+               case REALM_HEX:\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
+                       if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);\r
+                       break;\r
+               }\r
+               if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)\r
+               {\r
+                       s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell];\r
+                       s16b exp_gain = 0;\r
+\r
+                       if (cur_exp < SPELL_EXP_BEGINNER)\r
+                               exp_gain += 60;\r
+                       else if (cur_exp < SPELL_EXP_SKILLED)\r
+                       {\r
+                               if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))\r
+                                       exp_gain = 8;\r
+                       }\r
+                       else if (cur_exp < SPELL_EXP_EXPERT)\r
+                       {\r
+                               if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))\r
+                                       exp_gain = 2;\r
+                       }\r
+                       else if ((cur_exp < SPELL_EXP_MASTER) && !increment)\r
+                       {\r
+                               if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))\r
+                                       exp_gain = 1;\r
+                       }\r
+                       p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;\r
                }\r
-               break;\r
+       }\r
 \r
-       case 5:\r
-               if (name) return _("みね打ち", "Strike to Stun");\r
-               if (desc) return _("相手にダメージを与えないが、朦朧とさせる。", "Attempts to stun a monster in the adjacent.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
+       p_ptr->energy_use = 100;\r
 \r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
 \r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
+       /* Over-exert the player */\r
+       if (over_exerted)\r
+       {\r
+               int oops = need_mana;\r
 \r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_MINEUCHI);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
+               /* No mana left */\r
+               p_ptr->csp = 0;\r
+               p_ptr->csp_frac = 0;\r
 \r
-       case 6:\r
-               if (name) return _("カウンター", "Counter");\r
-               if (desc) return _("相手に攻撃されたときに反撃する。反撃するたびにMPを消費。", \r
-                       "Prepares to counterattack. When attack by a monster, strikes back using SP each time.");\r
-    \r
-               if (cast)\r
-               {\r
-                       if (p_ptr->riding)\r
-                       {\r
-                               msg_print(_("乗馬中には無理だ。", "You cannot do it when riding."));\r
-                               return NULL;\r
-                       }\r
-                       msg_print(_("相手の攻撃に対して身構えた。", "You prepare to counter blow."));\r
-                       p_ptr->counter = TRUE;\r
-               }\r
-               break;\r
+               msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));\r
 \r
-       case 7:\r
-               if (name) return _("払い抜け", "Harainuke");\r
-               if (desc) return _("攻撃した後、反対側に抜ける。", \r
-                       "Attacks monster with your weapons normally, then move through counter side of the monster.");\r
-    \r
-               if (cast)\r
-               {\r
-                       POSITION y, x;\r
+               /* Hack -- Bypass free action */\r
+               (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));\r
 \r
-                       if (p_ptr->riding)\r
-                       {\r
-                               msg_print(_("乗馬中には無理だ。", "You cannot do it when riding."));\r
-                               return NULL;\r
-                       }\r
-       \r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-       \r
-                       if (dir == 5) return NULL;\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-       \r
-                       if (!cave[y][x].m_idx)\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-       \r
-                       py_attack(y, x, 0);\r
-       \r
-                       if (!player_can_enter(cave[y][x].feat, 0) || is_trap(cave[y][x].feat))\r
-                               break;\r
-       \r
-                       y += ddy[dir];\r
-                       x += ddx[dir];\r
-       \r
-                       if (player_can_enter(cave[y][x].feat, 0) && !is_trap(cave[y][x].feat) && !cave[y][x].m_idx)\r
-                       {\r
-                               msg_print(NULL);\r
-       \r
-                               /* Move the player */\r
-                               (void)move_player_effect(y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);\r
-                       }\r
+               switch (realm)\r
+               {\r
+               case REALM_LIFE:\r
+                       chg_virtue(V_VITALITY, -10);\r
+                       break;\r
+               case REALM_DEATH:\r
+                       chg_virtue(V_UNLIFE, -10);\r
+                       break;\r
+               case REALM_DAEMON:\r
+                       chg_virtue(V_JUSTICE, 10);\r
+                       break;\r
+               case REALM_NATURE:\r
+                       chg_virtue(V_NATURE, -10);\r
+                       break;\r
+               case REALM_CRUSADE:\r
+                       chg_virtue(V_JUSTICE, -10);\r
+                       break;\r
+               case REALM_HEX:\r
+                       chg_virtue(V_COMPASSION, 10);\r
+                       break;\r
+               default:\r
+                       chg_virtue(V_KNOWLEDGE, -10);\r
+                       break;\r
                }\r
-               break;\r
 \r
-       case 8:\r
-               if (name) return _("サーペンツタン", "Serpent's Tongue");\r
-               if (desc) return _("毒耐性のないモンスターに大ダメージを与える。", "Attacks a monster with more damage unless it has resistance to poison.");\r
-    \r
-               if (cast)\r
+               /* Damage CON (possibly permanently) */\r
+               if (randint0(100) < 50)\r
                {\r
-                       int y, x;\r
+                       bool perm = (randint0(100) < 25);\r
 \r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
+                       msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));\r
 \r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
+                       /* Reduce constitution */\r
+                       (void)dec_stat(A_CON, 15 + randint1(10), perm);\r
+               }\r
+       }\r
 \r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_POISON);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 9:\r
-               if (name) return _("斬魔剣弐の太刀", "Zammaken");\r
-               if (desc) return _("生命のない邪悪なモンスターに大ダメージを与えるが、他のモンスターには全く効果がない。", \r
-                       "Attacks an evil unliving monster with great damage. No effect to other  monsters.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_ZANMA);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 10:\r
-               if (name) return _("裂風剣", "Wind Blast");\r
-               if (desc) return _("攻撃した相手を後方へ吹き飛ばす。", "Attacks an adjacent monster, and blow it away.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, 0);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-                       if (d_info[dungeon_type].flags1 & DF1_NO_MELEE)\r
-                       {\r
-                               return "";\r
-                       }\r
-                       if (cave[y][x].m_idx)\r
-                       {\r
-                               int i;\r
-                               POSITION ty = y, tx = x;\r
-                               POSITION oy = y, ox = x;\r
-                               MONSTER_IDX m_idx = cave[y][x].m_idx;\r
-                               monster_type *m_ptr = &m_list[m_idx];\r
-                               char m_name[80];\r
-       \r
-                               monster_desc(m_name, m_ptr, 0);\r
-       \r
-                               for (i = 0; i < 5; i++)\r
-                               {\r
-                                       y += ddy[dir];\r
-                                       x += ddx[dir];\r
-                                       if (cave_empty_bold(y, x))\r
-                                       {\r
-                                               ty = y;\r
-                                               tx = x;\r
-                                       }\r
-                                       else break;\r
-                               }\r
-                               if ((ty != oy) || (tx != ox))\r
-                               {\r
-                                       msg_format(_("%sを吹き飛ばした!", "You blow %s away!"), m_name);\r
-                                       cave[oy][ox].m_idx = 0;\r
-                                       cave[ty][tx].m_idx = m_idx;\r
-                                       m_ptr->fy = ty;\r
-                                       m_ptr->fx = tx;\r
-       \r
-                                       update_mon(m_idx, TRUE);\r
-                                       lite_spot(oy, ox);\r
-                                       lite_spot(ty, tx);\r
-       \r
-                                       if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))\r
-                                               p_ptr->update |= (PU_MON_LITE);\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 11:\r
-               if (name) return _("刀匠の目利き", "Judge");\r
-               if (desc) return _("武器・防具を1つ識別する。レベル45以上で武器・防具の能力を完全に知ることができる。", \r
-                       "Identifies a weapon or armor. Or *identifies* these at level 45.");\r
-    \r
-               if (cast)\r
-               {\r
-                       if (plev > 44)\r
-                       {\r
-                               if (!identify_fully(TRUE)) return NULL;\r
-                       }\r
-                       else\r
-                       {\r
-                               if (!ident_spell(TRUE)) return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 12:\r
-               if (name) return _("破岩斬", "Rock Smash");\r
-               if (desc) return _("岩を壊し、岩石系のモンスターに大ダメージを与える。", "Breaks rock. Or greatly damage a monster made by rocks.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_HAGAN);\r
-       \r
-                       if (!cave_have_flag_bold(y, x, FF_HURT_ROCK)) break;\r
-       \r
-                       /* Destroy the feature */\r
-                       cave_alter_feat(y, x, FF_HURT_ROCK);\r
-       \r
-                       /* Update some things */\r
-                       p_ptr->update |= (PU_FLOW);\r
-               }\r
-               break;\r
-\r
-       case 13:\r
-               if (name) return _("乱れ雪月花", "Midare-Setsugekka");\r
-               if (desc) return _("攻撃回数が増え、冷気耐性のないモンスターに大ダメージを与える。", \r
-                       "Attacks a monster with increased number of attacks and more damage unless it has resistance to cold.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_COLD);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 14:\r
-               if (name) return _("急所突き", "Spot Aiming");\r
-               if (desc) return _("モンスターを一撃で倒す攻撃を繰り出す。失敗すると1点しかダメージを与えられない。", \r
-                       "Attempts to kill a monster instantly. If failed cause only 1HP of damage.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_KYUSHO);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 15:\r
-               if (name) return _("魔神斬り", "Majingiri");\r
-               if (desc) return _("会心の一撃で攻撃する。攻撃がかわされやすい。", \r
-                       "Attempts to attack with critical hit. But this attack is easy to evade for a monster.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_MAJIN);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 16:\r
-               if (name) return _("捨て身", "Desperate Attack");\r
-               if (desc) return _("強力な攻撃を繰り出す。次のターンまでの間、食らうダメージが増える。", \r
-                       "Attacks with all of your power. But all damages you take will be doubled for one turn.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_SUTEMI);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-                       p_ptr->sutemi = TRUE;\r
-               }\r
-               break;\r
-\r
-       case 17:\r
-               if (name) return _("雷撃鷲爪斬", "Lightning Eagle");\r
-               if (desc) return _("電撃耐性のないモンスターに非常に大きいダメージを与える。", \r
-                       "Attacks a monster with more damage unless it has resistance to electricity.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_ELEC);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 18:\r
-               if (name) return _("入身", "Rush Attack");\r
-               if (desc) return _("素早く相手に近寄り攻撃する。", "Steps close to a monster and attacks at a time.");\r
-    \r
-               if (cast)\r
-               {\r
-                       if (!rush_attack(NULL)) return NULL;\r
-               }\r
-               break;\r
-\r
-       case 19:\r
-               if (name) return _("赤流渦", "Bloody Maelstrom");\r
-               if (desc) return _("自分自身も傷を作りつつ、その傷が深いほど大きい威力で全方向の敵を攻撃できる。生きていないモンスターには効果がない。", \r
-                       "Attacks all adjacent monsters with power corresponding to your cut status. Then increases your cut status. No effect to unliving monsters.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y = 0, x = 0;\r
-\r
-                       cave_type       *c_ptr;\r
-                       monster_type    *m_ptr;\r
-       \r
-                       if (p_ptr->cut < 300)\r
-                               set_cut(p_ptr->cut + 300);\r
-                       else\r
-                               set_cut(p_ptr->cut * 2);\r
-       \r
-                       for (dir = 0; dir < 8; dir++)\r
-                       {\r
-                               y = p_ptr->y + ddy_ddd[dir];\r
-                               x = p_ptr->x + ddx_ddd[dir];\r
-                               c_ptr = &cave[y][x];\r
-       \r
-                               /* Get the monster */\r
-                               m_ptr = &m_list[c_ptr->m_idx];\r
-       \r
-                               /* Hack -- attack monsters */\r
-                               if (c_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT)))\r
-                               {\r
-                                       if (!monster_living(&r_info[m_ptr->r_idx]))\r
-                                       {\r
-                                               char m_name[80];\r
-       \r
-                                               monster_desc(m_name, m_ptr, 0);\r
-                                               msg_format(_("%sには効果がない!", "%s is unharmed!"), m_name);\r
-                                       }\r
-                                       else py_attack(y, x, HISSATSU_SEKIRYUKA);\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 20:\r
-               if (name) return _("激震撃", "Earthquake Blow");\r
-               if (desc) return _("地震を起こす。", "Shakes dungeon structure, and results in random swapping of floors and walls.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y,x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_QUAKE);\r
-                       else\r
-                               earthquake(p_ptr->y, p_ptr->x, 10);\r
-               }\r
-               break;\r
-\r
-       case 21:\r
-               if (name) return _("地走り", "Crack");\r
-               if (desc) return _("衝撃波のビームを放つ。", "Fires a beam of shock wave.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int total_damage = 0, basedam, i;\r
-                       u32b flgs[TR_FLAG_SIZE];\r
-                       object_type *o_ptr;\r
-                       if (!get_aim_dir(&dir)) return NULL;\r
-                       msg_print(_("武器を大きく振り下ろした。", "You swing your weapon downward."));\r
-                       for (i = 0; i < 2; i++)\r
-                       {\r
-                               int damage;\r
-       \r
-                               if (!buki_motteruka(INVEN_RARM+i)) break;\r
-                               o_ptr = &inventory[INVEN_RARM+i];\r
-                               basedam = (o_ptr->dd * (o_ptr->ds + 1)) * 50;\r
-                               damage = o_ptr->to_d * 100;\r
-                               object_flags(o_ptr, flgs);\r
-                               if ((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD))\r
-                               {\r
-                                       /* vorpal blade */\r
-                                       basedam *= 5;\r
-                                       basedam /= 3;\r
-                               }\r
-                               else if (have_flag(flgs, TR_VORPAL))\r
-                               {\r
-                                       /* vorpal flag only */\r
-                                       basedam *= 11;\r
-                                       basedam /= 9;\r
-                               }\r
-                               damage += basedam;\r
-                               damage *= p_ptr->num_blow[i];\r
-                               total_damage += damage / 200;\r
-                               if (i) total_damage = total_damage*7/10;\r
-                       }\r
-                       fire_beam(GF_FORCE, dir, total_damage);\r
-               }\r
-               break;\r
-\r
-       case 22:\r
-               if (name) return _("気迫の雄叫び", "War Cry");\r
-               if (desc) return _("視界内の全モンスターに対して轟音の攻撃を行う。さらに、近くにいるモンスターを怒らせる。", \r
-                       "Damages all monsters in sight with sound. Aggravate nearby monsters.");\r
-    \r
-               if (cast)\r
-               {\r
-                       msg_print(_("雄叫びをあげた!", "You roar out!"));\r
-                       project_hack(GF_SOUND, randint1(plev * 3));\r
-                       aggravate_monsters(0);\r
-               }\r
-               break;\r
-\r
-       case 23:\r
-               if (name) return _("無双三段", "Musou-Sandan");\r
-               if (desc) return _("強力な3段攻撃を繰り出す。", "Attacks with powerful 3 strikes.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int i;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       for (i = 0; i < 3; i++)\r
-                       {\r
-                               POSITION y, x;\r
-                               POSITION ny, nx;\r
-                               MONSTER_IDX m_idx;\r
-                               cave_type *c_ptr;\r
-                               monster_type *m_ptr;\r
-       \r
-                               y = p_ptr->y + ddy[dir];\r
-                               x = p_ptr->x + ddx[dir];\r
-                               c_ptr = &cave[y][x];\r
-       \r
-                               if (c_ptr->m_idx)\r
-                                       py_attack(y, x, HISSATSU_3DAN);\r
-                               else\r
-                               {\r
-                                       msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                                       return NULL;\r
-                               }\r
-       \r
-                               if (d_info[dungeon_type].flags1 & DF1_NO_MELEE)\r
-                               {\r
-                                       return "";\r
-                               }\r
-       \r
-                               /* Monster is dead? */\r
-                               if (!c_ptr->m_idx) break;\r
-       \r
-                               ny = y + ddy[dir];\r
-                               nx = x + ddx[dir];\r
-                               m_idx = c_ptr->m_idx;\r
-                               m_ptr = &m_list[m_idx];\r
-       \r
-                               /* Monster cannot move back? */\r
-                               if (!monster_can_enter(ny, nx, &r_info[m_ptr->r_idx], 0))\r
-                               {\r
-                                       /* -more- */\r
-                                       if (i < 2) msg_print(NULL);\r
-                                       continue;\r
-                               }\r
-       \r
-                               c_ptr->m_idx = 0;\r
-                               cave[ny][nx].m_idx = m_idx;\r
-                               m_ptr->fy = ny;\r
-                               m_ptr->fx = nx;\r
-       \r
-                               update_mon(m_idx, TRUE);\r
-       \r
-                               /* Redraw the old spot */\r
-                               lite_spot(y, x);\r
-       \r
-                               /* Redraw the new spot */\r
-                               lite_spot(ny, nx);\r
-       \r
-                               /* Player can move forward? */\r
-                               if (player_can_enter(c_ptr->feat, 0))\r
-                               {\r
-                                       /* Move the player */\r
-                                       if (!move_player_effect(y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP)) break;\r
-                               }\r
-                               else\r
-                               {\r
-                                       break;\r
-                               }\r
-\r
-                               /* -more- */\r
-                               if (i < 2) msg_print(NULL);\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 24:\r
-               if (name) return _("吸血鬼の牙", "Vampire's Fang");\r
-               if (desc) return _("攻撃した相手の体力を吸いとり、自分の体力を回復させる。生命を持たないモンスターには通じない。", \r
-                       "Attacks with vampiric strikes which absorbs HP from a monster and gives them to you. No effect to unliving monsters.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_DRAIN);\r
-                       else\r
-                       {\r
-                                       msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 25:\r
-               if (name) return _("幻惑", "Moon Dazzling");\r
-               if (desc) return _("視界内の起きている全モンスターに朦朧、混乱、眠りを与えようとする。", "Attempts to stun, confuse and sleep all waking monsters.");\r
-    \r
-               if (cast)\r
-               {\r
-                       msg_print(_("武器を不規則に揺らした...", "You irregularly wave your weapon..."));\r
-                       project_hack(GF_ENGETSU, plev * 4);\r
-                       project_hack(GF_ENGETSU, plev * 4);\r
-                       project_hack(GF_ENGETSU, plev * 4);\r
-               }\r
-               break;\r
-\r
-       case 26:\r
-               if (name) return _("百人斬り", "Hundred Slaughter");\r
-               if (desc) return _("連続して入身でモンスターを攻撃する。攻撃するたびにMPを消費。MPがなくなるか、モンスターを倒せなかったら百人斬りは終了する。", \r
-                       "Performs a series of rush attacks. The series continues while killing each monster in a time and SP remains.");\r
-    \r
-               if (cast)\r
-               {\r
-                       const int mana_cost_per_monster = 8;\r
-                       bool is_new = TRUE;\r
-                       bool mdeath;\r
-\r
-                       do\r
-                       {\r
-                               if (!rush_attack(&mdeath)) break;\r
-                               if (is_new)\r
-                               {\r
-                                       /* Reserve needed mana point */\r
-                                       p_ptr->csp -= technic_info[REALM_HISSATSU - MIN_TECHNIC][26].smana;\r
-                                       is_new = FALSE;\r
-                               }\r
-                               else\r
-                                       p_ptr->csp -= mana_cost_per_monster;\r
-\r
-                               if (!mdeath) break;\r
-                               command_dir = 0;\r
-\r
-                               p_ptr->redraw |= PR_MANA;\r
-                               handle_stuff();\r
-                       }\r
-                       while (p_ptr->csp > mana_cost_per_monster);\r
-\r
-                       if (is_new) return NULL;\r
-       \r
-                       /* Restore reserved mana */\r
-                       p_ptr->csp += technic_info[REALM_HISSATSU - MIN_TECHNIC][26].smana;\r
-               }\r
-               break;\r
-\r
-       case 27:\r
-               if (name) return _("天翔龍閃", "Dragonic Flash");\r
-               if (desc) return _("視界内の場所を指定して、その場所と自分の間にいる全モンスターを攻撃し、その場所に移動する。", \r
-                       "Runs toward given location while attacking all monsters on the path.");\r
-    \r
-               if (cast)\r
-               {\r
-                       POSITION y, x;\r
-\r
-                       if (!tgt_pt(&x, &y)) return NULL;\r
-\r
-                       if (!cave_player_teleportable_bold(y, x, 0L) ||\r
-                           (distance(y, x, p_ptr->y, p_ptr->x) > MAX_SIGHT / 2) ||\r
-                           !projectable(p_ptr->y, p_ptr->x, y, x))\r
-                       {\r
-                               msg_print(_("失敗!", "You cannot move to that place!"));\r
-                               break;\r
-                       }\r
-                       if (p_ptr->anti_tele)\r
-                       {\r
-                               msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));\r
-                               break;\r
-                       }\r
-                       project(0, 0, y, x, HISSATSU_ISSEN, GF_ATTACK, PROJECT_BEAM | PROJECT_KILL, -1);\r
-                       teleport_player_to(y, x, 0L);\r
-               }\r
-               break;\r
-\r
-       case 28:\r
-               if (name) return _("二重の剣撃", "Twin Slash");\r
-               if (desc) return _("1ターンで2度攻撃を行う。", "double attacks at a time.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int x, y;\r
-       \r
-                       if (!get_rep_dir(&dir, FALSE)) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                       {\r
-                               py_attack(y, x, 0);\r
-                               if (cave[y][x].m_idx)\r
-                               {\r
-                                       handle_stuff();\r
-                                       py_attack(y, x, 0);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "You don't see any monster in this direction"));\r
-                               return NULL;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 29:\r
-               if (name) return _("虎伏絶刀勢", "Kofuku-Zettousei");\r
-               if (desc) return _("強力な攻撃を行い、近くの場所にも効果が及ぶ。", "Performs a powerful attack which even effect nearby monsters.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int total_damage = 0, basedam, i;\r
-                       int y, x;\r
-                       u32b flgs[TR_FLAG_SIZE];\r
-                       object_type *o_ptr;\r
-       \r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (d_info[dungeon_type].flags1 & DF1_NO_MELEE)\r
-                       {\r
-                               msg_print(_("なぜか攻撃することができない。", "Something prevent you from attacking."));\r
-                               return "";\r
-                       }\r
-                       msg_print(_("武器を大きく振り下ろした。", "You swing your weapon downward."));\r
-                       for (i = 0; i < 2; i++)\r
-                       {\r
-                               int damage;\r
-                               if (!buki_motteruka(INVEN_RARM+i)) break;\r
-                               o_ptr = &inventory[INVEN_RARM+i];\r
-                               basedam = (o_ptr->dd * (o_ptr->ds + 1)) * 50;\r
-                               damage = o_ptr->to_d * 100;\r
-                               object_flags(o_ptr, flgs);\r
-                               if ((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD))\r
-                               {\r
-                                       /* vorpal blade */\r
-                                       basedam *= 5;\r
-                                       basedam /= 3;\r
-                               }\r
-                               else if (have_flag(flgs, TR_VORPAL))\r
-                               {\r
-                                       /* vorpal flag only */\r
-                                       basedam *= 11;\r
-                                       basedam /= 9;\r
-                               }\r
-                               damage += basedam;\r
-                               damage += p_ptr->to_d[i] * 100;\r
-                               damage *= p_ptr->num_blow[i];\r
-                               total_damage += (damage / 100);\r
-                       }\r
-                       project(0, (cave_have_flag_bold(y, x, FF_PROJECT) ? 5 : 0), y, x, total_damage * 3 / 2, GF_METEOR, PROJECT_KILL | PROJECT_JUMP | PROJECT_ITEM, -1);\r
-               }\r
-               break;\r
-\r
-       case 30:\r
-               if (name) return _("慶雲鬼忍剣", "Keiun-Kininken");\r
-               if (desc) return _("自分もダメージをくらうが、相手に非常に大きなダメージを与える。アンデッドには特に効果がある。", \r
-                       "Attacks a monster with extremely powerful damage. But you also takes some damages. Hurts a undead monster greatly.");\r
-    \r
-               if (cast)\r
-               {\r
-                       int y, x;\r
-\r
-                       if (!get_rep_dir2(&dir)) return NULL;\r
-                       if (dir == 5) return NULL;\r
-\r
-                       y = p_ptr->y + ddy[dir];\r
-                       x = p_ptr->x + ddx[dir];\r
-\r
-                       if (cave[y][x].m_idx)\r
-                               py_attack(y, x, HISSATSU_UNDEAD);\r
-                       else\r
-                       {\r
-                               msg_print(_("その方向にはモンスターはいません。", "There is no monster."));\r
-                               return NULL;\r
-                       }\r
-                       take_hit(DAMAGE_NOESCAPE, 100 + randint1(100), _("慶雲鬼忍剣を使った衝撃", "exhaustion on using Keiun-Kininken"), -1);\r
-               }\r
-               break;\r
-\r
-       case 31:\r
-               if (name) return _("切腹", "Harakiri");\r
-               if (desc) return _("「武士道とは、死ぬことと見つけたり。」", "'Busido is found in death'");\r
-\r
-               if (cast)\r
-               {\r
-                       int i;\r
-                       if (!get_check(_("本当に自殺しますか?", "Do you really want to commit suicide? "))) return NULL;\r
-                               /* Special Verification for suicide */\r
-                       prt(_("確認のため '@' を押して下さい。", "Please verify SUICIDE by typing the '@' sign: "), 0, 0);\r
-       \r
-                       flush();\r
-                       i = inkey();\r
-                       prt("", 0, 0);\r
-                       if (i != '@') return NULL;\r
-                       if (p_ptr->total_winner)\r
-                       {\r
-                               take_hit(DAMAGE_FORCE, 9999, "Seppuku", -1);\r
-                               p_ptr->total_winner = TRUE;\r
-                       }\r
-                       else\r
-                       {\r
-                               msg_print(_("武士道とは、死ぬことと見つけたり。", "Meaning of Bushi-do is found in the death."));\r
-                               take_hit(DAMAGE_FORCE, 9999, "Seppuku", -1);\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-\r
-       return "";\r
-}\r
-\r
-/*!\r
- * @brief 呪術領域の武器呪縛の対象にできる武器かどうかを返す。 / An "item_tester_hook" for offer\r
- * @param o_ptr オブジェクト構造体の参照ポインタ\r
- * @return 呪縛可能な武器ならばTRUEを返す\r
- */\r
-static bool item_tester_hook_weapon_except_bow(object_type *o_ptr)\r
-{\r
-       switch (o_ptr->tval)\r
-       {\r
-               case TV_SWORD:\r
-               case TV_HAFTED:\r
-               case TV_POLEARM:\r
-               case TV_DIGGING:\r
-               {\r
-                       return (TRUE);\r
-               }\r
-       }\r
-\r
-       return (FALSE);\r
-}\r
-\r
-/*!\r
- * @brief 呪術領域の各処理に使える呪われた装備かどうかを返す。 / An "item_tester_hook" for offer\r
- * @param o_ptr オブジェクト構造体の参照ポインタ\r
- * @return 使える装備ならばTRUEを返す\r
- */\r
-static bool item_tester_hook_cursed(object_type *o_ptr)\r
-{\r
-       return (bool)(object_is_cursed(o_ptr));\r
-}\r
-\r
-/*!\r
- * @brief 呪術領域魔法の各処理を行う\r
- * @param spell 魔法ID\r
- * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST / SPELL_CONT / SPELL_STOP)\r
- * @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST / SPELL_CONT / SPELL_STOP 時はNULL文字列を返す。\r
- */\r
-static cptr do_hex_spell(SPELL_IDX spell, BIT_FLAGS mode)\r
-{\r
-       bool name = (mode == SPELL_NAME) ? TRUE : FALSE;\r
-       bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;\r
-       bool info = (mode == SPELL_INFO) ? TRUE : FALSE;\r
-       bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;\r
-       bool cont = (mode == SPELL_CONT) ? TRUE : FALSE;\r
-       bool stop = (mode == SPELL_STOP) ? TRUE : FALSE;\r
-\r
-       bool add = TRUE;\r
-\r
-       PLAYER_LEVEL plev = p_ptr->lev;\r
-       HIT_POINT power;\r
-\r
-       switch (spell)\r
-       {\r
-       /*** 1st book (0-7) ***/\r
-       case 0:\r
-               if (name) return _("邪なる祝福", "Evily blessing");\r
-               if (desc) return _("祝福により攻撃精度と防御力が上がる。", "Attempts to increase +to_hit of a weapon and AC");\r
-               if (cast)\r
-               {\r
-                       if (!p_ptr->blessed)\r
-                       {\r
-                               msg_print(_("高潔な気分になった!", "You feel righteous!"));\r
-                       }\r
-               }\r
-               if (stop)\r
-               {\r
-                       if (!p_ptr->blessed)\r
-                       {\r
-                               msg_print(_("高潔な気分が消え失せた。", "The prayer has expired."));\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 1:\r
-               if (name) return _("軽傷の治癒", "Cure light wounds");\r
-               if (desc) return _("HPや傷を少し回復させる。", "Heals cut and HP a little.");\r
-               if (info) return info_heal(1, 10, 0);\r
-               if (cast)\r
-               {\r
-                       msg_print(_("気分が良くなってくる。", "You feel better and better."));\r
-               }\r
-               if (cast || cont)\r
-               {\r
-                       hp_player(damroll(1, 10));\r
-                       set_cut(p_ptr->cut - 10);\r
-               }\r
-               break;\r
-\r
-       case 2:\r
-               if (name) return _("悪魔のオーラ", "Demonic aura");\r
-               if (desc) return _("炎のオーラを身にまとい、回復速度が速くなる。", "Gives fire aura and regeneration.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("体が炎のオーラで覆われた。", "You have enveloped by fiery aura!"));\r
-               }\r
-               if (stop)\r
-               {\r
-                       msg_print(_("炎のオーラが消え去った。", "Fiery aura disappeared."));\r
-               }\r
-               break;\r
-\r
-       case 3:\r
-               if (name) return _("悪臭霧", "Stinking mist");\r
-               if (desc) return _("視界内のモンスターに微弱量の毒のダメージを与える。", "Deals few damages of poison to all monsters in your sight.");\r
-               power = plev / 2 + 5;\r
-               if (info) return info_damage(1, power, 0);\r
-               if (cast || cont)\r
-               {\r
-                       project_hack(GF_POIS, randint1(power));\r
-               }\r
-               break;\r
-\r
-       case 4:\r
-               if (name) return _("腕力強化", "Extra might");\r
-               if (desc) return _("術者の腕力を上昇させる。", "Attempts to increase your strength.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("何だか力が湧いて来る。", "You feel you get stronger."));\r
-               }\r
-               break;\r
-\r
-       case 5:\r
-               if (name) return _("武器呪縛", "Curse weapon");\r
-               if (desc) return _("装備している武器を呪う。", "Curses your weapon.");\r
-               if (cast)\r
-               {\r
-                       OBJECT_IDX item;\r
-                       cptr q, s;\r
-                       char o_name[MAX_NLEN];\r
-                       object_type *o_ptr;\r
-                       u32b f[TR_FLAG_SIZE];\r
-\r
-                       item_tester_hook = item_tester_hook_weapon_except_bow;\r
-                       q = _("どれを呪いますか?", "Which weapon do you curse?");\r
-                       s = _("武器を装備していない。", "You wield no weapons.");\r
-\r
-                       if (!get_item(&item, q, s, (USE_EQUIP))) return FALSE;\r
-\r
-                       o_ptr = &inventory[item];\r
-                       object_desc(o_name, o_ptr, OD_NAME_ONLY);\r
-                       object_flags(o_ptr, f);\r
-\r
-                       if (!get_check(format(_("本当に %s を呪いますか?", "Do you curse %s, really?"), o_name))) return FALSE;\r
-\r
-                       if (!one_in_(3) &&\r
-                               (object_is_artifact(o_ptr) || have_flag(f, TR_BLESSED)))\r
-                       {\r
-                               msg_format(_("%s は呪いを跳ね返した。", "%s resists the effect."), o_name);\r
-                               if (one_in_(3))\r
-                               {\r
-                                       if (o_ptr->to_d > 0)\r
-                                       {\r
-                                               o_ptr->to_d -= randint1(3) % 2;\r
-                                               if (o_ptr->to_d < 0) o_ptr->to_d = 0;\r
-                                       }\r
-                                       if (o_ptr->to_h > 0)\r
-                                       {\r
-                                               o_ptr->to_h -= randint1(3) % 2;\r
-                                               if (o_ptr->to_h < 0) o_ptr->to_h = 0;\r
-                                       }\r
-                                       if (o_ptr->to_a > 0)\r
-                                       {\r
-                                               o_ptr->to_a -= randint1(3) % 2;\r
-                                               if (o_ptr->to_a < 0) o_ptr->to_a = 0;\r
-                                       }\r
-                                       msg_format(_("%s は劣化してしまった。", "Your %s was disenchanted!"), o_name);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               int curse_rank = 0;\r
-                               msg_format(_("恐怖の暗黒オーラがあなたの%sを包み込んだ!", "A terrible black aura blasts your %s!"), o_name);\r
-                               o_ptr->curse_flags |= (TRC_CURSED);\r
-\r
-                               if (object_is_artifact(o_ptr) || object_is_ego(o_ptr))\r
-                               {\r
-\r
-                                       if (one_in_(3)) o_ptr->curse_flags |= (TRC_HEAVY_CURSE);\r
-                                       if (one_in_(666))\r
-                                       {\r
-                                               o_ptr->curse_flags |= (TRC_TY_CURSE);\r
-                                               if (one_in_(666)) o_ptr->curse_flags |= (TRC_PERMA_CURSE);\r
-\r
-                                               add_flag(o_ptr->art_flags, TR_AGGRAVATE);\r
-                                               add_flag(o_ptr->art_flags, TR_VORPAL);\r
-                                               add_flag(o_ptr->art_flags, TR_VAMPIRIC);\r
-                                               msg_print(_("血だ!血だ!血だ!", "Blood, Blood, Blood!"));\r
-                                               curse_rank = 2;\r
-                                       }\r
-                               }\r
-\r
-                               o_ptr->curse_flags |= get_curse(curse_rank, o_ptr);\r
-                       }\r
-\r
-                       p_ptr->update |= (PU_BONUS);\r
-                       add = FALSE;\r
-               }\r
-               break;\r
-\r
-       case 6:\r
-               if (name) return _("邪悪感知", "Evil detection");\r
-               if (desc) return _("周囲の邪悪なモンスターを感知する。", "Detects evil monsters.");\r
-               if (info) return info_range(MAX_SIGHT);\r
-               if (cast)\r
-               {\r
-                       msg_print(_("邪悪な生物の存在を感じ取ろうとした。", "You attend to the presence of evil creatures."));\r
-               }\r
-               break;\r
-\r
-       case 7:\r
-               if (name) return _("我慢", "Patience");\r
-               if (desc) return _("数ターン攻撃を耐えた後、受けたダメージを地獄の業火として周囲に放出する。", \r
-                       "Bursts hell fire strongly after patients any damage while few turns.");\r
-               power = MIN(200, (HEX_REVENGE_POWER(p_ptr) * 2));\r
-               if (info) return info_damage(0, 0, power);\r
-               if (cast)\r
-               {\r
-                       int a = 3 - (p_ptr->pspeed - 100) / 10;\r
-                       MAGIC_NUM2 r = 3 + randint1(3) + MAX(0, MIN(3, a));\r
-\r
-                       if (HEX_REVENGE_TURN(p_ptr) > 0)\r
-                       {\r
-                               msg_print(_("すでに我慢をしている。", "You are already patienting."));\r
-                               return NULL;\r
-                       }\r
-\r
-                       HEX_REVENGE_TYPE(p_ptr) = 1;\r
-                       HEX_REVENGE_TURN(p_ptr) = r;\r
-                       HEX_REVENGE_POWER(p_ptr) = 0;\r
-                       msg_print(_("じっと耐えることにした。", "You decide to patient all damages."));\r
-                       add = FALSE;\r
-               }\r
-               if (cont)\r
-               {\r
-                       int rad = 2 + (power / 50);\r
-\r
-                       HEX_REVENGE_TURN(p_ptr)--;\r
-\r
-                       if ((HEX_REVENGE_TURN(p_ptr) <= 0) || (power >= 200))\r
-                       {\r
-                               msg_print(_("我慢が解かれた!", "Time for end of patioence!"));\r
-                               if (power)\r
-                               {\r
-                                       project(0, rad, p_ptr->y, p_ptr->x, power, GF_HELL_FIRE,\r
-                                               (PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL), -1);\r
-                               }\r
-                               if (p_ptr->wizard)\r
-                               {\r
-                                       msg_format(_("%d点のダメージを返した。", "You return %d damages."), power);\r
-                               }\r
-\r
-                               /* Reset */\r
-                               HEX_REVENGE_TYPE(p_ptr) = 0;\r
-                               HEX_REVENGE_TURN(p_ptr) = 0;\r
-                               HEX_REVENGE_POWER(p_ptr) = 0;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       /*** 2nd book (8-15) ***/\r
-       case 8:\r
-               if (name) return _("氷の鎧", "Ice armor");\r
-               if (desc) return _("氷のオーラを身にまとい、防御力が上昇する。", "Gives fire aura and bonus to AC.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("体が氷の鎧で覆われた。", "You have enveloped by ice armor!"));\r
-               }\r
-               if (stop)\r
-               {\r
-                       msg_print(_("氷の鎧が消え去った。", "Ice armor disappeared."));\r
-               }\r
-               break;\r
-\r
-       case 9:\r
-               if (name) return _("重傷の治癒", "Cure serious wounds");\r
-               if (desc) return _("体力や傷を多少回復させる。", "Heals cut and HP more.");\r
-               if (info) return info_heal(2, 10, 0);\r
-               if (cast)\r
-               {\r
-                       msg_print(_("気分が良くなってくる。", "You feel better and better."));\r
-               }\r
-               if (cast || cont)\r
-               {\r
-                       hp_player(damroll(2, 10));\r
-                       set_cut((p_ptr->cut / 2) - 10);\r
-               }\r
-               break;\r
-\r
-       case 10:\r
-               if (name) return _("薬品吸入", "Inhail potion");\r
-               if (desc) return _("呪文詠唱を中止することなく、薬の効果を得ることができる。", "Quaffs a potion without canceling of casting a spell.");\r
-               if (cast)\r
-               {\r
-                       CASTING_HEX_FLAGS(p_ptr) |= (1L << HEX_INHAIL);\r
-                       do_cmd_quaff_potion();\r
-                       CASTING_HEX_FLAGS(p_ptr) &= ~(1L << HEX_INHAIL);\r
-                       add = FALSE;\r
-               }\r
-               break;\r
-\r
-       case 11:\r
-               if (name) return _("衰弱の霧", "Hypodynamic mist");\r
-               if (desc) return _("視界内のモンスターに微弱量の衰弱属性のダメージを与える。", \r
-                       "Deals few damages of hypodynamia to all monsters in your sight.");\r
-               power = (plev / 2) + 5;\r
-               if (info) return info_damage(1, power, 0);\r
-               if (cast || cont)\r
-               {\r
-                       project_hack(GF_HYPODYNAMIA, randint1(power));\r
-               }\r
-               break;\r
-\r
-       case 12:\r
-               if (name) return _("魔剣化", "Swords to runeswords");\r
-               if (desc) return _("武器の攻撃力を上げる。切れ味を得、呪いに応じて与えるダメージが上昇し、善良なモンスターに対するダメージが2倍になる。", \r
-                       "Gives vorpal ability to your weapon. Increases damages by your weapon acccording to curse of your weapon.");\r
-               if (cast)\r
-               {\r
-#ifdef JP\r
-                       msg_print("あなたの武器が黒く輝いた。");\r
-#else\r
-                       if (!empty_hands(FALSE))\r
-                               msg_print("Your weapons glow bright black.");\r
-                       else\r
-                               msg_print("Your weapon glows bright black.");\r
-#endif\r
-               }\r
-               if (stop)\r
-               {\r
-#ifdef JP\r
-                       msg_print("武器の輝きが消え去った。");\r
-#else\r
-                       msg_format("Brightness of weapon%s disappeared.", (empty_hands(FALSE)) ? "" : "s");\r
-#endif\r
-               }\r
-               break;\r
-\r
-       case 13:\r
-               if (name) return _("混乱の手", "Touch of confusion");\r
-               if (desc) return _("攻撃した際モンスターを混乱させる。", "Confuses a monster when you attack.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("あなたの手が赤く輝き始めた。", "Your hands glow bright red."));\r
-               }\r
-               if (stop)\r
-               {\r
-                       msg_print(_("手の輝きがなくなった。", "Brightness on your hands disappeard."));\r
-               }\r
-               break;\r
-\r
-       case 14:\r
-               if (name) return _("肉体強化", "Building up");\r
-               if (desc) return _("術者の腕力、器用さ、耐久力を上昇させる。攻撃回数の上限を 1 増加させる。", \r
-                       "Attempts to increases your strength, dexterity and constitusion.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("身体が強くなった気がした。", "You feel your body is developed more now."));\r
-               }\r
-               break;\r
-\r
-       case 15:\r
-               if (name) return _("反テレポート結界", "Anti teleport barrier");\r
-               if (desc) return _("視界内のモンスターのテレポートを阻害するバリアを張る。", "Obstructs all teleportations by monsters in your sight.");\r
-               power = plev * 3 / 2;\r
-               if (info) return info_power(power);\r
-               if (cast)\r
-               {\r
-                       msg_print(_("テレポートを防ぐ呪いをかけた。", "You feel anyone can not teleport except you."));\r
-               }\r
-               break;\r
-\r
-       /*** 3rd book (16-23) ***/\r
-       case 16:\r
-               if (name) return _("衝撃のクローク", "Cloak of shock");\r
-               if (desc) return _("電気のオーラを身にまとい、動きが速くなる。", "Gives lightning aura and a bonus to speed.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("体が稲妻のオーラで覆われた。", "You have enveloped by electrical aura!"));\r
-               }\r
-               if (stop)\r
-               {\r
-                       msg_print(_("稲妻のオーラが消え去った。", "Electrical aura disappeared."));\r
-               }\r
-               break;\r
-\r
-       case 17:\r
-               if (name) return _("致命傷の治癒", "Cure critical wounds");\r
-               if (desc) return _("体力や傷を回復させる。", "Heals cut and HP greatry.");\r
-               if (info) return info_heal(4, 10, 0);\r
-               if (cast)\r
-               {\r
-                       msg_print(_("気分が良くなってくる。", "You feel better and better."));\r
-               }\r
-               if (cast || cont)\r
-               {\r
-                       hp_player(damroll(4, 10));\r
-                       set_stun(0);\r
-                       set_cut(0);\r
-                       set_poisoned(0);\r
-               }\r
-               break;\r
-\r
-       case 18:\r
-               if (name) return _("呪力封入", "Recharging");\r
-               if (desc) return _("魔法の道具に魔力を再充填する。", "Recharges a magic device.");\r
-               power = plev * 2;\r
-               if (info) return info_power(power);\r
-               if (cast)\r
-               {\r
-                       if (!recharge(power)) return NULL;\r
-                       add = FALSE;\r
-               }\r
-               break;\r
-\r
-       case 19:\r
-               if (name) return _("死者復活", "Animate Dead");\r
-               if (desc) return _("死体を蘇らせてペットにする。", "Raises corpses and skeletons from dead.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("死者への呼びかけを始めた。", "You start to call deads.!"));\r
-               }\r
-               if (cast || cont)\r
-               {\r
-                       animate_dead(0, p_ptr->y, p_ptr->x);\r
-               }\r
-               break;\r
-\r
-       case 20:\r
-               if (name) return _("防具呪縛", "Curse armor");\r
-               if (desc) return _("装備している防具に呪いをかける。", "Curse a piece of armour that you wielding.");\r
-               if (cast)\r
-               {\r
-                       OBJECT_IDX item;\r
-                       cptr q, s;\r
-                       char o_name[MAX_NLEN];\r
-                       object_type *o_ptr;\r
-                       u32b f[TR_FLAG_SIZE];\r
-\r
-                       item_tester_hook = object_is_armour;\r
-                       q = _("どれを呪いますか?", "Which piece of armour do you curse?");\r
-                       s = _("防具を装備していない。", "You wield no piece of armours.");\r
-\r
-                       if (!get_item(&item, q, s, (USE_EQUIP))) return FALSE;\r
-\r
-                       o_ptr = &inventory[item];\r
-                       object_desc(o_name, o_ptr, OD_NAME_ONLY);\r
-                       object_flags(o_ptr, f);\r
-\r
-                       if (!get_check(format(_("本当に %s を呪いますか?", "Do you curse %s, really?"), o_name))) return FALSE;\r
-\r
-                       if (!one_in_(3) &&\r
-                               (object_is_artifact(o_ptr) || have_flag(f, TR_BLESSED)))\r
-                       {\r
-                               msg_format(_("%s は呪いを跳ね返した。", "%s resists the effect."), o_name);\r
-                               if (one_in_(3))\r
-                               {\r
-                                       if (o_ptr->to_d > 0)\r
-                                       {\r
-                                               o_ptr->to_d -= randint1(3) % 2;\r
-                                               if (o_ptr->to_d < 0) o_ptr->to_d = 0;\r
-                                       }\r
-                                       if (o_ptr->to_h > 0)\r
-                                       {\r
-                                               o_ptr->to_h -= randint1(3) % 2;\r
-                                               if (o_ptr->to_h < 0) o_ptr->to_h = 0;\r
-                                       }\r
-                                       if (o_ptr->to_a > 0)\r
-                                       {\r
-                                               o_ptr->to_a -= randint1(3) % 2;\r
-                                               if (o_ptr->to_a < 0) o_ptr->to_a = 0;\r
-                                       }\r
-                                       msg_format(_("%s は劣化してしまった。", "Your %s was disenchanted!"), o_name);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               int curse_rank = 0;\r
-                               msg_format(_("恐怖の暗黒オーラがあなたの%sを包み込んだ!", "A terrible black aura blasts your %s!"), o_name);\r
-                               o_ptr->curse_flags |= (TRC_CURSED);\r
-\r
-                               if (object_is_artifact(o_ptr) || object_is_ego(o_ptr))\r
-                               {\r
-\r
-                                       if (one_in_(3)) o_ptr->curse_flags |= (TRC_HEAVY_CURSE);\r
-                                       if (one_in_(666))\r
-                                       {\r
-                                               o_ptr->curse_flags |= (TRC_TY_CURSE);\r
-                                               if (one_in_(666)) o_ptr->curse_flags |= (TRC_PERMA_CURSE);\r
-\r
-                                               add_flag(o_ptr->art_flags, TR_AGGRAVATE);\r
-                                               add_flag(o_ptr->art_flags, TR_RES_POIS);\r
-                                               add_flag(o_ptr->art_flags, TR_RES_DARK);\r
-                                               add_flag(o_ptr->art_flags, TR_RES_NETHER);\r
-                                               msg_print(_("血だ!血だ!血だ!", "Blood, Blood, Blood!"));\r
-                                               curse_rank = 2;\r
-                                       }\r
-                               }\r
-\r
-                               o_ptr->curse_flags |= get_curse(curse_rank, o_ptr);\r
-                       }\r
-\r
-                       p_ptr->update |= (PU_BONUS);\r
-                       add = FALSE;\r
-               }\r
-               break;\r
-\r
-       case 21:\r
-               if (name) return _("影のクローク", "Cloak of shadow");\r
-               if (desc) return _("影のオーラを身にまとい、敵に影のダメージを与える。", "Gives aura of shadow.");\r
-               if (cast)\r
-               {\r
-                       object_type *o_ptr = &inventory[INVEN_OUTER];\r
-\r
-                       if (!o_ptr->k_idx)\r
-                       {\r
-                               msg_print(_("クロークを身につけていない!", "You don't ware any cloak."));\r
-                               return NULL;\r
-                       }\r
-                       else if (!object_is_cursed(o_ptr))\r
-                       {\r
-                               msg_print(_("クロークは呪われていない!", "Your cloak is not cursed."));\r
-                               return NULL;\r
-                       }\r
-                       else\r
-                       {\r
-                               msg_print(_("影のオーラを身にまとった。", "You have enveloped by shadow aura!"));\r
-                       }\r
-               }\r
-               if (cont)\r
-               {\r
-                       object_type *o_ptr = &inventory[INVEN_OUTER];\r
-\r
-                       if ((!o_ptr->k_idx) || (!object_is_cursed(o_ptr)))\r
-                       {\r
-                               do_spell(REALM_HEX, spell, SPELL_STOP);\r
-                               CASTING_HEX_FLAGS(p_ptr) &= ~(1L << spell);\r
-                               CASTING_HEX_NUM(p_ptr)--;\r
-                               if (!SINGING_SONG_ID(p_ptr)) set_action(ACTION_NONE);\r
-                       }\r
-               }\r
-               if (stop)\r
-               {\r
-                       msg_print(_("影のオーラが消え去った。", "Shadow aura disappeared."));\r
-               }\r
-               break;\r
-\r
-       case 22:\r
-               if (name) return _("苦痛を魔力に", "Pains to mana");\r
-               if (desc) return _("視界内のモンスターに精神ダメージ与え、魔力を吸い取る。", "Deals psychic damages to all monsters in sight, and drains some mana.");\r
-               power = plev * 3 / 2;\r
-               if (info) return info_damage(1, power, 0);\r
-               if (cast || cont)\r
-               {\r
-                       project_hack(GF_PSI_DRAIN, randint1(power));\r
-               }\r
-               break;\r
-\r
-       case 23:\r
-               if (name) return _("目には目を", "Eye for an eye");\r
-               if (desc) return _("打撃や魔法で受けたダメージを、攻撃元のモンスターにも与える。", "Returns same damage which you got to the monster which damaged you.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("復讐したい欲望にかられた。", "You wish strongly you want to revenge anything."));\r
-               }\r
-               break;\r
-\r
-       /*** 4th book (24-31) ***/\r
-       case 24:\r
-               if (name) return _("反増殖結界", "Anti multiply barrier");\r
-               if (desc) return _("その階の増殖するモンスターの増殖を阻止する。", "Obstructs all multiplying by monsters in entire floor.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("増殖を阻止する呪いをかけた。", "You feel anyone can not already multiply."));\r
-               }\r
-               break;\r
-\r
-       case 25:\r
-               if (name) return _("全復活", "Restoration");\r
-               if (desc) return _("経験値を徐々に復活し、減少した能力値を回復させる。", "Restores experience and status.");\r
-               if (cast)\r
-               {\r
-                       msg_print(_("体が元の活力を取り戻し始めた。", "You feel your lost status starting to return."));\r
-               }\r
-               if (cast || cont)\r
-               {\r
-                       bool flag = FALSE;\r
-                       int d = (p_ptr->max_exp - p_ptr->exp);\r
-                       int r = (p_ptr->exp / 20);\r
-                       int i;\r
-\r
-                       if (d > 0)\r
-                       {\r
-                               if (d < r)\r
-                                       p_ptr->exp = p_ptr->max_exp;\r
-                               else\r
-                                       p_ptr->exp += r;\r
-\r
-                               /* Check the experience */\r
-                               check_experience();\r
-\r
-                               flag = TRUE;\r
-                       }\r
-                       for (i = A_STR; i < 6; i ++)\r
-                       {\r
-                               if (p_ptr->stat_cur[i] < p_ptr->stat_max[i])\r
-                               {\r
-                                       if (p_ptr->stat_cur[i] < 18)\r
-                                               p_ptr->stat_cur[i]++;\r
-                                       else\r
-                                               p_ptr->stat_cur[i] += 10;\r
-\r
-                                       if (p_ptr->stat_cur[i] > p_ptr->stat_max[i])\r
-                                               p_ptr->stat_cur[i] = p_ptr->stat_max[i];\r
-\r
-                                       /* Recalculate bonuses */\r
-                                       p_ptr->update |= (PU_BONUS);\r
-\r
-                                       flag = TRUE;\r
-                               }\r
-                       }\r
-\r
-                       if (!flag)\r
-                       {\r
-                               msg_format(_("%sの呪文の詠唱をやめた。", "Finish casting '%^s'."), do_spell(REALM_HEX, HEX_RESTORE, SPELL_NAME));\r
-                               CASTING_HEX_FLAGS(p_ptr) &= ~(1L << HEX_RESTORE);\r
-                               if (cont) CASTING_HEX_NUM(p_ptr)--;\r
-                               if (CASTING_HEX_NUM(p_ptr)) p_ptr->action = ACTION_NONE;\r
-\r
-                               /* Redraw status */\r
-                               p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);\r
-                               p_ptr->redraw |= (PR_EXTRA);\r
-\r
-                               return "";\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case 26:\r
-               if (name) return _("呪力吸収", "Drain curse power");\r
-               if (desc) return _("呪われた武器の呪いを吸収して魔力を回復する。", "Drains curse on your weapon and heals SP a little.");\r
-               if (cast)\r
-               {\r
-                       OBJECT_IDX item;\r
-                       cptr s, q;\r
-                       u32b f[TR_FLAG_SIZE];\r
-                       object_type *o_ptr;\r
-\r
-                       item_tester_hook = item_tester_hook_cursed;\r
-                       q = _("どの装備品から吸収しますか?", "Which cursed equipment do you drain mana from?");\r
-                       s = _("呪われたアイテムを装備していない。", "You have no cursed equipment.");\r
-\r
-                       if (!get_item(&item, q, s, (USE_EQUIP))) return FALSE;\r
-\r
-                       o_ptr = &inventory[item];\r
-                       object_flags(o_ptr, f);\r
-\r
-                       p_ptr->csp += (p_ptr->lev / 5) + randint1(p_ptr->lev / 5);\r
-                       if (have_flag(f, TR_TY_CURSE) || (o_ptr->curse_flags & TRC_TY_CURSE)) p_ptr->csp += randint1(5);\r
-                       if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;\r
-\r
-                       if (o_ptr->curse_flags & TRC_PERMA_CURSE)\r
-                       {\r
-                               /* Nothing */\r
-                       }\r
-                       else if (o_ptr->curse_flags & TRC_HEAVY_CURSE)\r
-                       {\r
-                               if (one_in_(7))\r
-                               {\r
-                                       msg_print(_("呪いを全て吸い取った。", "Heavy curse vanished away."));\r
-                                       o_ptr->curse_flags = 0L;\r
-                               }\r
-                       }\r
-                       else if ((o_ptr->curse_flags & (TRC_CURSED)) && one_in_(3))\r
-                       {\r
-                               msg_print(_("呪いを全て吸い取った。", "Curse vanished away."));\r
-                               o_ptr->curse_flags = 0L;\r
-                       }\r
-\r
-                       add = FALSE;\r
-               }\r
-               break;\r
-\r
-       case 27:\r
-               if (name) return _("吸血の刃", "Swords to vampires");\r
-               if (desc) return _("吸血属性で攻撃する。", "Gives vampiric ability to your weapon.");\r
-               if (cast)\r
-               {\r
-#ifdef JP\r
-                       msg_print("あなたの武器が血を欲している。");\r
-#else\r
-                       if (!empty_hands(FALSE))\r
-                               msg_print("Your weapons want more blood now.");\r
-                       else\r
-                               msg_print("Your weapon wants more blood now.");\r
-#endif\r
-               }\r
-               if (stop)\r
-               {\r
-#ifdef JP\r
-                       msg_print("武器の渇望が消え去った。");\r
-#else\r
-                       msg_format("Thirsty of weapon%s disappeared.", (empty_hands(FALSE)) ? "" : "s");\r
-#endif\r
-               }\r
-               break;\r
-\r
-       case 28:\r
-               if (name) return _("朦朧の言葉", "Word of stun");\r
-               if (desc) return _("視界内のモンスターを朦朧とさせる。", "Stuns all monsters in your sight.");\r
-               power = plev * 4;\r
-               if (info) return info_power(power);\r
-               if (cast || cont)\r
-               {\r
-                       stun_monsters(power);\r
-               }\r
-               break;\r
-\r
-       case 29:\r
-               if (name) return _("影移動", "Moving into shadow");\r
-               if (desc) return _("モンスターの隣のマスに瞬間移動する。", "Teleports you close to a monster.");\r
-               if (cast)\r
-               {\r
-                       int i, dir;\r
-                       POSITION y, x;\r
-                       bool flag;\r
-\r
-                       for (i = 0; i < 3; i++)\r
-                       {\r
-                               if (!tgt_pt(&x, &y)) return FALSE;\r
-\r
-                               flag = FALSE;\r
-\r
-                               for (dir = 0; dir < 8; dir++)\r
-                               {\r
-                                       int dy = y + ddy_ddd[dir];\r
-                                       int dx = x + ddx_ddd[dir];\r
-                                       if (dir == 5) continue;\r
-                                       if(cave[dy][dx].m_idx) flag = TRUE;\r
-                               }\r
-\r
-                               if (!cave_empty_bold(y, x) || (cave[y][x].info & CAVE_ICKY) ||\r
-                                       (distance(y, x, p_ptr->y, p_ptr->x) > plev + 2))\r
-                               {\r
-                                       msg_print(_("そこには移動できない。", "Can not teleport to there."));\r
-                                       continue;\r
-                               }\r
-                               break;\r
-                       }\r
-\r
-                       if (flag && randint0(plev * plev / 2))\r
-                       {\r
-                               teleport_player_to(y, x, 0L);\r
-                       }\r
-                       else\r
-                       {\r
-                               msg_print(_("おっと!", "Oops!"));\r
-                               teleport_player(30, 0L);\r
-                       }\r
-\r
-                       add = FALSE;\r
-               }\r
-               break;\r
-\r
-       case 30:\r
-               if (name) return _("反魔法結界", "Anti magic barrier");\r
-               if (desc) return _("視界内のモンスターの魔法を阻害するバリアを張る。", "Obstructs all magic spell of monsters in your sight.");\r
-               power = plev * 3 / 2;\r
-               if (info) return info_power(power);\r
-               if (cast)\r
-               {\r
-                       msg_print(_("魔法を防ぐ呪いをかけた。", "You feel anyone can not cast spells except you."));\r
-               }\r
-               break;\r
-\r
-       case 31:\r
-               if (name) return _("復讐の宣告", "Revenge sentence");\r
-               if (desc) return _("数ターン後にそれまで受けたダメージに応じた威力の地獄の劫火の弾を放つ。", \r
-                       "Fires  a ball of hell fire to try revenging after few turns.");\r
-               power = HEX_REVENGE_POWER(p_ptr);\r
-               if (info) return info_damage(0, 0, power);\r
-               if (cast)\r
-               {\r
-                       MAGIC_NUM2 r;\r
-                       int a = 3 - (p_ptr->pspeed - 100) / 10;\r
-                       r = 1 + randint1(2) + MAX(0, MIN(3, a));\r
-\r
-                       if (HEX_REVENGE_TURN(p_ptr) > 0)\r
-                       {\r
-                               msg_print(_("すでに復讐は宣告済みだ。", "You already pronounced your revenge."));\r
-                               return NULL;\r
-                       }\r
-\r
-                       HEX_REVENGE_TYPE(p_ptr) = 2;\r
-                       HEX_REVENGE_TURN(p_ptr) = r;\r
-                       msg_format(_("あなたは復讐を宣告した。あと %d ターン。", "You pronounce your revenge. %d turns left."), r);\r
-                       add = FALSE;\r
-               }\r
-               if (cont)\r
-               {\r
-                       HEX_REVENGE_TURN(p_ptr)--;\r
-\r
-                       if (HEX_REVENGE_TURN(p_ptr) <= 0)\r
-                       {\r
-                               int dir;\r
-\r
-                               if (power)\r
-                               {\r
-                                       command_dir = 0;\r
-\r
-                                       do\r
-                                       {\r
-                                               msg_print(_("復讐の時だ!", "Time to revenge!"));\r
-                                       }\r
-                                       while (!get_aim_dir(&dir));\r
-\r
-                                       fire_ball(GF_HELL_FIRE, dir, power, 1);\r
-\r
-                                       if (p_ptr->wizard)\r
-                                       {\r
-                                               msg_format(_("%d点のダメージを返した。", "You return %d damages."), power);\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       msg_print(_("復讐する気が失せた。", "You are not a mood to revenge."));\r
-                               }\r
-                               HEX_REVENGE_POWER(p_ptr) = 0;\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-\r
-       /* start casting */\r
-       if ((cast) && (add))\r
-       {\r
-               /* add spell */\r
-               CASTING_HEX_FLAGS(p_ptr) |= 1L << (spell);\r
-               CASTING_HEX_NUM(p_ptr)++;\r
-\r
-               if (p_ptr->action != ACTION_SPELL) set_action(ACTION_SPELL);\r
-       }\r
-\r
-       /* Redraw status */\r
-       if (!info)\r
-       {\r
-               p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);\r
-               p_ptr->redraw |= (PR_EXTRA | PR_HP | PR_MANA);\r
-       }\r
-\r
-       return "";\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法処理のメインルーチン\r
- * @param realm 魔法領域のID\r
- * @param spell 各領域の魔法ID\r
- * @param mode 求める処理\r
- * @return 各領域魔法に各種テキストを求めた場合は文字列参照ポインタ、そうでない場合はNULLポインタを返す。\r
- */\r
-cptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode)\r
-{\r
-       switch (realm)\r
-       {\r
-       case REALM_LIFE:     return do_life_spell(spell, mode);\r
-       case REALM_SORCERY:  return do_sorcery_spell(spell, mode);\r
-       case REALM_NATURE:   return do_nature_spell(spell, mode);\r
-       case REALM_CHAOS:    return do_chaos_spell(spell, mode);\r
-       case REALM_DEATH:    return do_death_spell(spell, mode);\r
-       case REALM_TRUMP:    return do_trump_spell(spell, mode);\r
-       case REALM_ARCANE:   return do_arcane_spell(spell, mode);\r
-       case REALM_CRAFT:    return do_craft_spell(spell, mode);\r
-       case REALM_DAEMON:   return do_daemon_spell(spell, mode);\r
-       case REALM_CRUSADE:  return do_crusade_spell(spell, mode);\r
-       case REALM_MUSIC:    return do_music_spell(spell, mode);\r
-       case REALM_HISSATSU: return do_hissatsu_spell(spell, mode);\r
-       case REALM_HEX:      return do_hex_spell(spell, mode);\r
-       }\r
-\r
-       return NULL;\r
+       p_ptr->window |= (PW_PLAYER);\r
+       p_ptr->window |= (PW_SPELL);\r
 }\r