OSDN Git Service

#37353 狂戦士化の効果をberserk()にまとめる。
[hengband/hengband.git] / src / spells2.c
index 1cbf7ba..0a7ceec 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "angband.h"
 #include "grid.h"
+#include "trap.h"
 
 
 /*!
@@ -2902,7 +2903,7 @@ bool fire_ball(int typ, int dir, HIT_POINT dam, int rad)
 */
 bool fire_breath(int typ, int dir, HIT_POINT dam, int rad)
 {
-       fire_ball(typ, dir, dam, -rad);
+       return fire_ball(typ, dir, dam, -rad);
 }
 
 
@@ -4322,3 +4323,794 @@ void ring_of_power(int dir)
        }
 }
 
+/*!
+* @brief 運命の輪、並びにカオス的な効果の発動
+* @param spell ランダムな効果を選択するための基準ID
+* @return なし
+*/
+void wild_magic(int spell)
+{
+       int counter = 0;
+       int type = SUMMON_MOLD + randint0(6);
+
+       if (type < SUMMON_MOLD) type = SUMMON_MOLD;
+       else if (type > SUMMON_MIMIC) type = SUMMON_MIMIC;
+
+       switch (randint1(spell) + randint1(8) + 1)
+       {
+       case 1:
+       case 2:
+       case 3:
+               teleport_player(10, TELEPORT_PASSIVE);
+               break;
+       case 4:
+       case 5:
+       case 6:
+               teleport_player(100, TELEPORT_PASSIVE);
+               break;
+       case 7:
+       case 8:
+               teleport_player(200, TELEPORT_PASSIVE);
+               break;
+       case 9:
+       case 10:
+       case 11:
+               unlite_area(10, 3);
+               break;
+       case 12:
+       case 13:
+       case 14:
+               lite_area(damroll(2, 3), 2);
+               break;
+       case 15:
+               destroy_doors_touch();
+               break;
+       case 16: case 17:
+               wall_breaker();
+       case 18:
+               sleep_monsters_touch();
+               break;
+       case 19:
+       case 20:
+               trap_creation(p_ptr->y, p_ptr->x);
+               break;
+       case 21:
+       case 22:
+               door_creation();
+               break;
+       case 23:
+       case 24:
+       case 25:
+               aggravate_monsters(0);
+               break;
+       case 26:
+               earthquake(p_ptr->y, p_ptr->x, 5);
+               break;
+       case 27:
+       case 28:
+               (void)gain_random_mutation(0);
+               break;
+       case 29:
+       case 30:
+               apply_disenchant(1);
+               break;
+       case 31:
+               lose_all_info();
+               break;
+       case 32:
+               fire_ball(GF_CHAOS, 0, spell + 5, 1 + (spell / 10));
+               break;
+       case 33:
+               wall_stone();
+               break;
+       case 34:
+       case 35:
+               while (counter++ < 8)
+               {
+                       (void)summon_specific(0, p_ptr->y, p_ptr->x, (dun_level * 3) / 2, type, (PM_ALLOW_GROUP | PM_NO_PET));
+               }
+               break;
+       case 36:
+       case 37:
+               activate_hi_summon(p_ptr->y, p_ptr->x, FALSE);
+               break;
+       case 38:
+               (void)summon_cyber(-1, p_ptr->y, p_ptr->x);
+               break;
+       default:
+       {
+               int count = 0;
+               (void)activate_ty_curse(FALSE, &count);
+               break;
+       }
+       }
+
+       return;
+}
+
+/*!
+* @brief カオス魔法「流星群」の処理としてプレイヤーを中心に隕石落下処理を10+1d10回繰り返す。
+* / Drop 10+1d10 meteor ball at random places near the player
+* @param dam ダメージ
+* @param rad 効力の半径
+* @return なし
+*/
+void cast_meteor(HIT_POINT dam, int rad)
+{
+       int i;
+       int b = 10 + randint1(10);
+
+       for (i = 0; i < b; i++)
+       {
+               POSITION y = 0, x = 0;
+               int count;
+
+               for (count = 0; count <= 20; count++)
+               {
+                       int dy, dx, d;
+
+                       x = p_ptr->x - 8 + randint0(17);
+                       y = p_ptr->y - 8 + randint0(17);
+
+                       dx = (p_ptr->x > x) ? (p_ptr->x - x) : (x - p_ptr->x);
+                       dy = (p_ptr->y > y) ? (p_ptr->y - y) : (y - p_ptr->y);
+
+                       /* Approximate distance */
+                       d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
+
+                       if (d >= 9) continue;
+
+                       if (!in_bounds(y, x) || !projectable(p_ptr->y, p_ptr->x, y, x)
+                               || !cave_have_flag_bold(y, x, FF_PROJECT)) continue;
+
+                       /* Valid position */
+                       break;
+               }
+
+               if (count > 20) continue;
+
+               project(0, rad, y, x, dam, GF_METEOR, PROJECT_KILL | PROJECT_JUMP | PROJECT_ITEM, -1);
+       }
+}
+
+
+/*!
+* @brief 破邪魔法「神の怒り」の処理としてターゲットを指定した後分解のボールを最大20回発生させる。
+* @param dam ダメージ
+* @param rad 効力の半径
+* @return ターゲットを指定し、実行したならばTRUEを返す。
+*/
+bool cast_wrath_of_the_god(HIT_POINT dam, int rad)
+{
+       int x, y, tx, ty;
+       int nx, ny;
+       int dir, i;
+       int b = 10 + randint1(10);
+
+       if (!get_aim_dir(&dir)) return FALSE;
+
+       /* Use the given direction */
+       tx = p_ptr->x + 99 * ddx[dir];
+       ty = p_ptr->y + 99 * ddy[dir];
+
+       /* Hack -- Use an actual "target" */
+       if ((dir == 5) && target_okay())
+       {
+               tx = target_col;
+               ty = target_row;
+       }
+
+       x = p_ptr->x;
+       y = p_ptr->y;
+
+       while (1)
+       {
+               /* Hack -- Stop at the target */
+               if ((y == ty) && (x == tx)) break;
+
+               ny = y;
+               nx = x;
+               mmove2(&ny, &nx, p_ptr->y, p_ptr->x, ty, tx);
+
+               /* Stop at maximum range */
+               if (MAX_RANGE <= distance(p_ptr->y, p_ptr->x, ny, nx)) break;
+
+               /* Stopped by walls/doors */
+               if (!cave_have_flag_bold(ny, nx, FF_PROJECT)) break;
+
+               /* Stopped by monsters */
+               if ((dir != 5) && cave[ny][nx].m_idx != 0) break;
+
+               /* Save the new location */
+               x = nx;
+               y = ny;
+       }
+       tx = x;
+       ty = y;
+
+       for (i = 0; i < b; i++)
+       {
+               int count = 20, d = 0;
+
+               while (count--)
+               {
+                       int dx, dy;
+
+                       x = tx - 5 + randint0(11);
+                       y = ty - 5 + randint0(11);
+
+                       dx = (tx > x) ? (tx - x) : (x - tx);
+                       dy = (ty > y) ? (ty - y) : (y - ty);
+
+                       /* Approximate distance */
+                       d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
+                       /* Within the radius */
+                       if (d < 5) break;
+               }
+
+               if (count < 0) continue;
+
+               /* Cannot penetrate perm walls */
+               if (!in_bounds(y, x) ||
+                       cave_stop_disintegration(y, x) ||
+                       !in_disintegration_range(ty, tx, y, x))
+                       continue;
+
+               project(0, rad, y, x, dam, GF_DISINTEGRATE, PROJECT_JUMP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL, -1);
+       }
+
+       return TRUE;
+}
+
+/*!
+* @brief 「ワンダー」のランダムな効果を決定して処理する。
+* @param dir 方向ID
+* @return なし
+* @details
+* This spell should become more useful (more controlled) as the\n
+* player gains experience levels.  Thus, add 1/5 of the player's\n
+* level to the die roll.  This eliminates the worst effects later on,\n
+* while keeping the results quite random.  It also allows some potent\n
+* effects only at high level.
+*/
+void cast_wonder(int dir)
+{
+       int plev = p_ptr->lev;
+       int die = randint1(100) + plev / 5;
+       int vir = virtue_number(V_CHANCE);
+
+       if (vir)
+       {
+               if (p_ptr->virtues[vir - 1] > 0)
+               {
+                       while (randint1(400) < p_ptr->virtues[vir - 1]) die++;
+               }
+               else
+               {
+                       while (randint1(400) < (0 - p_ptr->virtues[vir - 1])) die--;
+               }
+       }
+
+       if (die < 26)
+               chg_virtue(V_CHANCE, 1);
+
+       if (die > 100)
+       {
+               msg_print(_("あなたは力がみなぎるのを感じた!", "You feel a surge of power!"));
+       }
+
+       if (die < 8) clone_monster(dir);
+       else if (die < 14) speed_monster(dir, plev);
+       else if (die < 26) heal_monster(dir, damroll(4, 6));
+       else if (die < 31) poly_monster(dir, plev);
+       else if (die < 36)
+               fire_bolt_or_beam(beam_chance() - 10, GF_MISSILE, dir,
+                       damroll(3 + ((plev - 1) / 5), 4));
+       else if (die < 41) confuse_monster(dir, plev);
+       else if (die < 46) fire_ball(GF_POIS, dir, 20 + (plev / 2), 3);
+       else if (die < 51) (void)lite_line(dir, damroll(6, 8));
+       else if (die < 56)
+               fire_bolt_or_beam(beam_chance() - 10, GF_ELEC, dir,
+                       damroll(3 + ((plev - 5) / 4), 8));
+       else if (die < 61)
+               fire_bolt_or_beam(beam_chance() - 10, GF_COLD, dir,
+                       damroll(5 + ((plev - 5) / 4), 8));
+       else if (die < 66)
+               fire_bolt_or_beam(beam_chance(), GF_ACID, dir,
+                       damroll(6 + ((plev - 5) / 4), 8));
+       else if (die < 71)
+               fire_bolt_or_beam(beam_chance(), GF_FIRE, dir,
+                       damroll(8 + ((plev - 5) / 4), 8));
+       else if (die < 76) hypodynamic_bolt(dir, 75);
+       else if (die < 81) fire_ball(GF_ELEC, dir, 30 + plev / 2, 2);
+       else if (die < 86) fire_ball(GF_ACID, dir, 40 + plev, 2);
+       else if (die < 91) fire_ball(GF_ICE, dir, 70 + plev, 3);
+       else if (die < 96) fire_ball(GF_FIRE, dir, 80 + plev, 3);
+       else if (die < 101) hypodynamic_bolt(dir, 100 + plev);
+       else if (die < 104)
+       {
+               earthquake(p_ptr->y, p_ptr->x, 12);
+       }
+       else if (die < 106)
+       {
+               (void)destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE);
+       }
+       else if (die < 108)
+       {
+               symbol_genocide(plev + 50, TRUE);
+       }
+       else if (die < 110) dispel_monsters(120);
+       else /* RARE */
+       {
+               dispel_monsters(150);
+               slow_monsters(plev);
+               sleep_monsters(plev);
+               hp_player(300);
+       }
+}
+
+
+/*!
+* @brief 「悪霊召喚」のランダムな効果を決定して処理する。
+* @param dir 方向ID
+* @return なし
+*/
+void cast_invoke_spirits(int dir)
+{
+       int plev = p_ptr->lev;
+       int die = randint1(100) + plev / 5;
+       int vir = virtue_number(V_CHANCE);
+
+       if (vir)
+       {
+               if (p_ptr->virtues[vir - 1] > 0)
+               {
+                       while (randint1(400) < p_ptr->virtues[vir - 1]) die++;
+               }
+               else
+               {
+                       while (randint1(400) < (0 - p_ptr->virtues[vir - 1])) die--;
+               }
+       }
+
+       msg_print(_("あなたは死者たちの力を招集した...", "You call on the power of the dead..."));
+       if (die < 26)
+               chg_virtue(V_CHANCE, 1);
+
+       if (die > 100)
+       {
+               msg_print(_("あなたはおどろおどろしい力のうねりを感じた!", "You feel a surge of eldritch force!"));
+       }
+
+       if (die < 8)
+       {
+               msg_print(_("なんてこった!あなたの周りの地面から朽ちた人影が立ち上がってきた!",
+                       "Oh no! Mouldering forms rise from the earth around you!"));
+
+               (void)summon_specific(0, p_ptr->y, p_ptr->x, dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
+               chg_virtue(V_UNLIFE, 1);
+       }
+       else if (die < 14)
+       {
+               msg_print(_("名状し難い邪悪な存在があなたの心を通り過ぎて行った...", "An unnamable evil brushes against your mind..."));
+
+               set_afraid(p_ptr->afraid + randint1(4) + 4);
+       }
+       else if (die < 26)
+       {
+               msg_print(_("あなたの頭に大量の幽霊たちの騒々しい声が押し寄せてきた...",
+                       "Your head is invaded by a horde of gibbering spectral voices..."));
+
+               set_confused(p_ptr->confused + randint1(4) + 4);
+       }
+       else if (die < 31)
+       {
+               poly_monster(dir, plev);
+       }
+       else if (die < 36)
+       {
+               fire_bolt_or_beam(beam_chance() - 10, GF_MISSILE, dir,
+                       damroll(3 + ((plev - 1) / 5), 4));
+       }
+       else if (die < 41)
+       {
+               confuse_monster(dir, plev);
+       }
+       else if (die < 46)
+       {
+               fire_ball(GF_POIS, dir, 20 + (plev / 2), 3);
+       }
+       else if (die < 51)
+       {
+               (void)lite_line(dir, damroll(6, 8));
+       }
+       else if (die < 56)
+       {
+               fire_bolt_or_beam(beam_chance() - 10, GF_ELEC, dir,
+                       damroll(3 + ((plev - 5) / 4), 8));
+       }
+       else if (die < 61)
+       {
+               fire_bolt_or_beam(beam_chance() - 10, GF_COLD, dir,
+                       damroll(5 + ((plev - 5) / 4), 8));
+       }
+       else if (die < 66)
+       {
+               fire_bolt_or_beam(beam_chance(), GF_ACID, dir,
+                       damroll(6 + ((plev - 5) / 4), 8));
+       }
+       else if (die < 71)
+       {
+               fire_bolt_or_beam(beam_chance(), GF_FIRE, dir,
+                       damroll(8 + ((plev - 5) / 4), 8));
+       }
+       else if (die < 76)
+       {
+               hypodynamic_bolt(dir, 75);
+       }
+       else if (die < 81)
+       {
+               fire_ball(GF_ELEC, dir, 30 + plev / 2, 2);
+       }
+       else if (die < 86)
+       {
+               fire_ball(GF_ACID, dir, 40 + plev, 2);
+       }
+       else if (die < 91)
+       {
+               fire_ball(GF_ICE, dir, 70 + plev, 3);
+       }
+       else if (die < 96)
+       {
+               fire_ball(GF_FIRE, dir, 80 + plev, 3);
+       }
+       else if (die < 101)
+       {
+               hypodynamic_bolt(dir, 100 + plev);
+       }
+       else if (die < 104)
+       {
+               earthquake(p_ptr->y, p_ptr->x, 12);
+       }
+       else if (die < 106)
+       {
+               (void)destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE);
+       }
+       else if (die < 108)
+       {
+               symbol_genocide(plev + 50, TRUE);
+       }
+       else if (die < 110)
+       {
+               dispel_monsters(120);
+       }
+       else
+       { /* RARE */
+               dispel_monsters(150);
+               slow_monsters(plev);
+               sleep_monsters(plev);
+               hp_player(300);
+       }
+
+       if (die < 31)
+       {
+               msg_print(_("陰欝な声がクスクス笑う。「もうすぐおまえは我々の仲間になるだろう。弱き者よ。」",
+                       "Sepulchral voices chuckle. 'Soon you will join us, mortal.'"));
+       }
+}
+
+/*!
+* @brief トランプ領域の「シャッフル」の効果をランダムに決めて処理する。
+* @return なし
+*/
+void cast_shuffle(void)
+{
+       int plev = p_ptr->lev;
+       int dir;
+       int die;
+       int vir = virtue_number(V_CHANCE);
+       int i;
+
+       /* Card sharks and high mages get a level bonus */
+       if ((p_ptr->pclass == CLASS_ROGUE) ||
+               (p_ptr->pclass == CLASS_HIGH_MAGE) ||
+               (p_ptr->pclass == CLASS_SORCERER))
+               die = (randint1(110)) + plev / 5;
+       else
+               die = randint1(120);
+
+
+       if (vir)
+       {
+               if (p_ptr->virtues[vir - 1] > 0)
+               {
+                       while (randint1(400) < p_ptr->virtues[vir - 1]) die++;
+               }
+               else
+               {
+                       while (randint1(400) < (0 - p_ptr->virtues[vir - 1])) die--;
+               }
+       }
+
+       msg_print(_("あなたはカードを切って一枚引いた...", "You shuffle the deck and draw a card..."));
+
+       if (die < 30)
+               chg_virtue(V_CHANCE, 1);
+
+       if (die < 7)
+       {
+               msg_print(_("なんてこった!《死》だ!", "Oh no! It's Death!"));
+
+               for (i = 0; i < randint1(3); i++)
+                       activate_hi_summon(p_ptr->y, p_ptr->x, FALSE);
+       }
+       else if (die < 14)
+       {
+               msg_print(_("なんてこった!《悪魔》だ!", "Oh no! It's the Devil!"));
+               summon_specific(0, p_ptr->y, p_ptr->x, dun_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
+       }
+       else if (die < 18)
+       {
+               int count = 0;
+               msg_print(_("なんてこった!《吊られた男》だ!", "Oh no! It's the Hanged Man."));
+               activate_ty_curse(FALSE, &count);
+       }
+       else if (die < 22)
+       {
+               msg_print(_("《不調和の剣》だ。", "It's the swords of discord."));
+               aggravate_monsters(0);
+       }
+       else if (die < 26)
+       {
+               msg_print(_("《愚者》だ。", "It's the Fool."));
+               do_dec_stat(A_INT);
+               do_dec_stat(A_WIS);
+       }
+       else if (die < 30)
+       {
+               msg_print(_("奇妙なモンスターの絵だ。", "It's the picture of a strange monster."));
+               trump_summoning(1, FALSE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), (32 + randint1(6)), PM_ALLOW_GROUP | PM_ALLOW_UNIQUE);
+       }
+       else if (die < 33)
+       {
+               msg_print(_("《月》だ。", "It's the Moon."));
+               unlite_area(10, 3);
+       }
+       else if (die < 38)
+       {
+               msg_print(_("《運命の輪》だ。", "It's the Wheel of Fortune."));
+               wild_magic(randint0(32));
+       }
+       else if (die < 40)
+       {
+               msg_print(_("テレポート・カードだ。", "It's a teleport trump card."));
+               teleport_player(10, TELEPORT_PASSIVE);
+       }
+       else if (die < 42)
+       {
+               msg_print(_("《正義》だ。", "It's Justice."));
+               set_blessed(p_ptr->lev, FALSE);
+       }
+       else if (die < 47)
+       {
+               msg_print(_("テレポート・カードだ。", "It's a teleport trump card."));
+               teleport_player(100, TELEPORT_PASSIVE);
+       }
+       else if (die < 52)
+       {
+               msg_print(_("テレポート・カードだ。", "It's a teleport trump card."));
+               teleport_player(200, TELEPORT_PASSIVE);
+       }
+       else if (die < 60)
+       {
+               msg_print(_("《塔》だ。", "It's the Tower."));
+               wall_breaker();
+       }
+       else if (die < 72)
+       {
+               msg_print(_("《節制》だ。", "It's Temperance."));
+               sleep_monsters_touch();
+       }
+       else if (die < 80)
+       {
+               msg_print(_("《塔》だ。", "It's the Tower."));
+
+               earthquake(p_ptr->y, p_ptr->x, 5);
+       }
+       else if (die < 82)
+       {
+               msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
+               trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_MOLD, 0L);
+       }
+       else if (die < 84)
+       {
+               msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
+               trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_BAT, 0L);
+       }
+       else if (die < 86)
+       {
+               msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
+               trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_VORTEX, 0L);
+       }
+       else if (die < 88)
+       {
+               msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
+               trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_COIN_MIMIC, 0L);
+       }
+       else if (die < 96)
+       {
+               msg_print(_("《恋人》だ。", "It's the Lovers."));
+
+               if (get_aim_dir(&dir))
+                       charm_monster(dir, MIN(p_ptr->lev, 20));
+       }
+       else if (die < 101)
+       {
+               msg_print(_("《隠者》だ。", "It's the Hermit."));
+               wall_stone();
+       }
+       else if (die < 111)
+       {
+               msg_print(_("《審判》だ。", "It's the Judgement."));
+               do_cmd_rerate(FALSE);
+               lose_all_mutations();
+       }
+       else if (die < 120)
+       {
+               msg_print(_("《太陽》だ。", "It's the Sun."));
+               chg_virtue(V_KNOWLEDGE, 1);
+               chg_virtue(V_ENLIGHTEN, 1);
+               wiz_lite(FALSE);
+       }
+       else
+       {
+               msg_print(_("《世界》だ。", "It's the World."));
+               if (p_ptr->exp < PY_MAX_EXP)
+               {
+                       s32b ee = (p_ptr->exp / 25) + 1;
+                       if (ee > 5000) ee = 5000;
+                       msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
+                       gain_exp(ee);
+               }
+       }
+}
+
+bool_hack life_stream(bool_hack message, bool_hack virtue)
+{
+       if(virtue)
+       {
+               chg_virtue(V_VITALITY, 1);
+               chg_virtue(V_UNLIFE, -5);
+       }
+       if(message)
+       {
+               msg_print(_("体中に生命力が満ちあふれてきた!", "You feel life flow through your body!"));
+       }
+       restore_level();
+       (void)set_poisoned(0);
+       (void)set_blind(0);
+       (void)set_confused(0);
+       (void)set_image(0);
+       (void)set_stun(0);
+       (void)set_cut(0);
+       (void)restore_all_status();
+       (void)set_shero(0, TRUE);
+       update_stuff();
+       hp_player(5000);
+
+       return TRUE;
+}
+
+bool_hack heroism(int base)
+{
+       bool_hack ident = FALSE;
+       if(set_afraid(0)) ident = TRUE;
+       if(set_hero(p_ptr->hero + randint1(base) + base, FALSE)) ident = TRUE;
+       if(hp_player(10)) ident = TRUE;
+       return ident;
+}
+
+bool_hack berserk(int base)
+{
+       bool_hack ident = FALSE;
+       if (set_afraid(0)) ident = TRUE;
+       if (set_shero(p_ptr->hero + randint1(base) + base, FALSE)) ident = TRUE;
+       if (hp_player(30)) ident = TRUE;
+       return ident;
+}
+
+bool_hack cure_light_wounds(int dice, int sides)
+{
+       bool_hack ident = FALSE;
+       if (hp_player(damroll(dice, sides))) ident = TRUE;
+       if (set_blind(0)) ident = TRUE;
+       if (set_cut(p_ptr->cut - 10)) ident = TRUE;
+       if (set_shero(0, TRUE)) ident = TRUE;
+       return ident;
+}
+
+bool_hack cure_serious_wounds(int dice, int sides)
+{
+       bool_hack ident = FALSE;
+       if (hp_player(damroll(dice, sides))) ident = TRUE;
+       if (set_blind(0)) ident = TRUE;
+       if (set_confused(0)) ident = TRUE;
+       if (set_cut((p_ptr->cut / 2) - 50)) ident = TRUE;
+       if (set_shero(0, TRUE)) ident = TRUE;
+       return ident;
+}
+
+bool_hack cure_critical_wounds(HIT_POINT pow)
+{
+       bool_hack ident = FALSE;
+       if (hp_player(pow)) ident = TRUE;
+       if (set_blind(0)) ident = TRUE;
+       if (set_confused(0)) ident = TRUE;
+       if (set_poisoned(0)) ident = TRUE;
+       if (set_stun(0)) ident = TRUE;
+       if (set_cut(0)) ident = TRUE;
+       if (set_shero(0, TRUE)) ident = TRUE;
+       return ident;
+}
+
+bool_hack true_healing(HIT_POINT pow)
+{
+       bool_hack ident = FALSE;
+       if (hp_player(pow)) ident = TRUE;
+       if (set_blind(0)) ident = TRUE;
+       if (set_confused(0)) ident = TRUE;
+       if (set_poisoned(0)) ident = TRUE;
+       if (set_stun(0)) ident = TRUE;
+       if (set_cut(0)) ident = TRUE;
+       if (set_image(0)) ident = TRUE;
+       return ident;
+}
+
+bool_hack restore_mana(bool_hack magic_eater)
+{
+       bool_hack ident = FALSE;
+
+       if (p_ptr->pclass == CLASS_MAGIC_EATER && magic_eater)
+       {
+               int i;
+               for (i = 0; i < EATER_EXT * 2; i++)
+               {
+                       p_ptr->magic_num1[i] += (p_ptr->magic_num2[i] < 10) ? EATER_CHARGE * 3 : p_ptr->magic_num2[i] * EATER_CHARGE / 3;
+                       if (p_ptr->magic_num1[i] > p_ptr->magic_num2[i] * EATER_CHARGE) p_ptr->magic_num1[i] = p_ptr->magic_num2[i] * EATER_CHARGE;
+               }
+               for (; i < EATER_EXT * 3; i++)
+               {
+                       KIND_OBJECT_IDX k_idx = lookup_kind(TV_ROD, i - EATER_EXT * 2);
+                       p_ptr->magic_num1[i] -= ((p_ptr->magic_num2[i] < 10) ? EATER_ROD_CHARGE * 3 : p_ptr->magic_num2[i] * EATER_ROD_CHARGE / 3)*k_info[k_idx].pval;
+                       if (p_ptr->magic_num1[i] < 0) p_ptr->magic_num1[i] = 0;
+               }
+               msg_print(_("頭がハッキリとした。", "You feel your head clear."));
+               p_ptr->window |= (PW_PLAYER);
+               ident = TRUE;
+       }
+       else if (p_ptr->csp < p_ptr->msp)
+       {
+               p_ptr->csp = p_ptr->msp;
+               p_ptr->csp_frac = 0;
+               msg_print(_("頭がハッキリとした。", "You feel your head clear."));
+               p_ptr->redraw |= (PR_MANA);
+               p_ptr->window |= (PW_PLAYER);
+               p_ptr->window |= (PW_SPELL);
+               ident = TRUE;
+       }
+
+       return ident;
+}
+
+bool restore_all_status(void)
+{
+       bool ident = FALSE; 
+       if (do_res_stat(A_STR)) ident = TRUE;
+       if (do_res_stat(A_INT)) ident = TRUE;
+       if (do_res_stat(A_WIS)) ident = TRUE;
+       if (do_res_stat(A_DEX)) ident = TRUE;
+       if (do_res_stat(A_CON)) ident = TRUE;
+       if (do_res_stat(A_CHR)) ident = TRUE;
+       return ident;
+}
+