OSDN Git Service

幻覚に関するバグ修正.
[hengband/hengband.git] / src / melee2.c
index a420f07..7757dbc 100644 (file)
@@ -1416,6 +1416,12 @@ static int check_hit2(int power, int level, int ac, int stun)
 }
 
 
+#define BLOW_EFFECT_TYPE_NONE  0
+#define BLOW_EFFECT_TYPE_FEAR  1
+#define BLOW_EFFECT_TYPE_SLEEP 2
+#define BLOW_EFFECT_TYPE_HEAL  3
+
+
 /* Monster attacks monster */
 static bool monst_attack_monst(int m_idx, int t_idx)
 {
@@ -1429,10 +1435,11 @@ static bool monst_attack_monst(int m_idx, int t_idx)
        int             ac, rlev, pt;
        char            m_name[80], t_name[80];
        char            temp[80];
-       bool            blinked, heal_effect;
+       bool            blinked;
        bool            explode = FALSE, touched = FALSE, fear = FALSE;
        int             y_saver = t_ptr->fy;
        int             x_saver = t_ptr->fx;
+       int             effect_type;
 
        bool see_m = is_seen(m_ptr);
        bool see_t = is_seen(t_ptr);
@@ -1832,8 +1839,8 @@ act = "%s
                        /* Roll out the damage */
                        damage = damroll(d_dice, d_side);
 
-                       /* Assume no healing effect */
-                       heal_effect = FALSE;
+                       /* Assume no effect */
+                       effect_type = BLOW_EFFECT_TYPE_NONE;
 
                        pt = GF_MISSILE;
 
@@ -1841,147 +1848,103 @@ act = "%s
                        switch (effect)
                        {
                        case 0:
-                               {
-                                       damage = 0;
-                                       pt = 0;
-                                       break;
-                               }
+                       case RBE_DR_MANA:
+                               damage = pt = 0;
+                               break;
 
                        case RBE_SUPERHURT:
+                               if ((randint1(rlev*2+250) > (ac+200)) || one_in_(13))
                                {
-                                       if ((randint1(rlev*2+250) > (ac+200)) || one_in_(13)) {
-                                               int tmp_damage = damage-(damage*((ac < 150) ? ac : 150)/250);
-                                               damage = MAX(damage, tmp_damage*2);
-                                               break;
-                                       }
-                               }
-                       case RBE_HURT:
-                               {
-                                       damage -= (damage * ((ac < 150) ? ac : 150) / 250);
+                                       int tmp_damage = damage - (damage * ((ac < 150) ? ac : 150) / 250);
+                                       damage = MAX(damage, tmp_damage * 2);
                                        break;
                                }
 
+                               /* Fall through */
+
+                       case RBE_HURT:
+                               damage -= (damage * ((ac < 150) ? ac : 150) / 250);
+                               break;
+
                        case RBE_POISON:
                        case RBE_DISEASE:
-                               {
-                                       pt = GF_POIS;
-                                       break;
-                               }
+                               pt = GF_POIS;
+                               break;
 
                        case RBE_UN_BONUS:
                        case RBE_UN_POWER:
-                               {
-                                       pt = GF_DISENCHANT;
-                                       break;
-                               }
-
-                       case RBE_EAT_FOOD:
-                       case RBE_EAT_LITE:
-                       case RBE_DR_MANA:
-                               {
-                                       pt = damage = 0;
-                                       break;
-                               }
+                               pt = GF_DISENCHANT;
+                               break;
 
                        case RBE_EAT_ITEM:
                        case RBE_EAT_GOLD:
-                               {
-                                       pt = damage = 0;
-                                       if ((p_ptr->riding != m_idx) && one_in_(2)) blinked = TRUE;
-                                       break;
-                               }
+                               if ((p_ptr->riding != m_idx) && one_in_(2)) blinked = TRUE;
+                               break;
+
+                       case RBE_EAT_FOOD:
+                       case RBE_EAT_LITE:
+                       case RBE_BLIND:
+                       case RBE_LOSE_STR:
+                       case RBE_LOSE_INT:
+                       case RBE_LOSE_WIS:
+                       case RBE_LOSE_DEX:
+                       case RBE_LOSE_CON:
+                       case RBE_LOSE_CHR:
+                       case RBE_LOSE_ALL:
+                               break;
 
                        case RBE_ACID:
-                               {
-                                       pt = GF_ACID;
-                                       break;
-                               }
+                               pt = GF_ACID;
+                               break;
 
                        case RBE_ELEC:
-                               {
-                                       pt = GF_ELEC;
-                                       break;
-                               }
+                               pt = GF_ELEC;
+                               break;
 
                        case RBE_FIRE:
-                               {
-                                       pt = GF_FIRE;
-                                       break;
-                               }
+                               pt = GF_FIRE;
+                               break;
 
                        case RBE_COLD:
-                               {
-                                       pt = GF_COLD;
-                                       break;
-                               }
-
-                       case RBE_BLIND:
-                               {
-                                       break;
-                               }
+                               pt = GF_COLD;
+                               break;
 
                        case RBE_CONFUSE:
-                               {
-                                       pt = GF_CONFUSION;
-                                       break;
-                               }
+                               pt = GF_CONFUSION;
+                               break;
 
                        case RBE_TERRIFY:
-                               {
-                                       pt = GF_TURN_ALL;
-                                       break;
-                               }
+                               effect_type = BLOW_EFFECT_TYPE_FEAR;
+                               break;
 
                        case RBE_PARALYZE:
-                               {
-                                       pt = GF_OLD_SLEEP; /* sort of close... */
-                                       break;
-                               }
+                               effect_type = BLOW_EFFECT_TYPE_SLEEP;
+                               break;
 
-                       case RBE_LOSE_STR:
-                       case RBE_LOSE_INT:
-                       case RBE_LOSE_WIS:
-                       case RBE_LOSE_DEX:
-                       case RBE_LOSE_CON:
-                       case RBE_LOSE_CHR:
-                       case RBE_LOSE_ALL:
-                               {
-                                       break;
-                               }
                        case RBE_SHATTER:
-                               {
-                                       damage -= (damage * ((ac < 150) ? ac : 150) / 250);
-                                       if (damage > 23)
-                                       {
-                                               earthquake(m_ptr->fy, m_ptr->fx, 8);
-                                       }
-                                       break;
-                               }
+                               damage -= (damage * ((ac < 150) ? ac : 150) / 250);
+                               if (damage > 23) earthquake_aux(m_ptr->fy, m_ptr->fx, 8, m_idx);
+                               break;
+
                        case RBE_EXP_10:
                        case RBE_EXP_20:
                        case RBE_EXP_40:
                        case RBE_EXP_80:
-                               {
-                                       pt = GF_NETHER;
-                                       break;
-                               }
+                               pt = GF_NETHER;
+                               break;
+
                        case RBE_TIME:
-                               {
-                                       pt = GF_TIME;
-                                       break;
-                               }
+                               pt = GF_TIME;
+                               break;
+
                        case RBE_EXP_VAMP:
-                               {
-                                       pt = GF_OLD_DRAIN;
-                                       heal_effect = TRUE;
-                                       break;
-                               }
+                               pt = GF_OLD_DRAIN;
+                               effect_type = BLOW_EFFECT_TYPE_HEAL;
+                               break;
 
                        default:
-                               {
-                                       pt = 0;
-                                       break;
-                               }
+                               pt = 0;
+                               break;
                        }
 
                        if (pt)
@@ -1990,11 +1953,22 @@ act = "%s
                                if (!explode)
                                {
                                        project(m_idx, 0, t_ptr->fy, t_ptr->fx,
-                                               (pt == GF_OLD_SLEEP ? r_ptr->level : damage), pt, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
+                                               damage, pt, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
                                }
 
-                               if (heal_effect)
+                               switch (effect_type)
                                {
+                               case BLOW_EFFECT_TYPE_FEAR:
+                                       project(m_idx, 0, t_ptr->fy, t_ptr->fx,
+                                               damage, GF_TURN_ALL, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
+                                       break;
+
+                               case BLOW_EFFECT_TYPE_SLEEP:
+                                       project(m_idx, 0, t_ptr->fy, t_ptr->fx,
+                                               r_ptr->level, GF_OLD_SLEEP, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
+                                       break;
+
+                               case BLOW_EFFECT_TYPE_HEAL:
                                        if ((monster_living(tr_ptr)) && (damage > 2))
                                        {
                                                bool did_heal = FALSE;
@@ -2013,13 +1987,13 @@ act = "%s
                                                if (see_m && did_heal)
                                                {
 #ifdef JP
-msg_format("%s¤ÏÂÎÎϤò²óÉü¤·¤¿¤è¤¦¤À¡£", m_name);
+                                                       msg_format("%s¤ÏÂÎÎϤò²óÉü¤·¤¿¤è¤¦¤À¡£", m_name);
 #else
                                                        msg_format("%^s appears healthier.", m_name);
 #endif
-
                                                }
                                        }
+                                       break;
                                }
 
                                if (touched)
@@ -2188,13 +2162,21 @@ msg_format("%s
                        mon_fight = TRUE;
                }
 
-               teleport_away(m_idx, MAX_SIGHT * 2 + 5, FALSE, FALSE);
+               teleport_away(m_idx, MAX_SIGHT * 2 + 5, 0L);
        }
 
        return TRUE;
 }
 
 
+static bool check_hp_for_feat_destruction(feature_type *f_ptr, monster_type *m_ptr)
+{
+       return !have_flag(f_ptr->flags, FF_GLASS) ||
+              (r_info[m_ptr->r_idx].flags2 & RF2_STUPID) ||
+              (m_ptr->hp >= MAX(m_ptr->maxhp / 3, 200));
+}
+
+
 /*
  * Process a monster
  *
@@ -2239,6 +2221,7 @@ static void process_monster(int m_idx)
        bool            do_turn;
        bool            do_move;
        bool            do_view;
+       bool            must_alter_to_move;
 
        bool            did_open_door;
        bool            did_bash_door;
@@ -2477,13 +2460,10 @@ static void process_monster(int m_idx)
 #endif
                }
 
-               if (m_ptr->ml)
+               /* Hack -- Count the wakings */
+               if (is_original_ap_and_seen(m_ptr) && (r_ptr->r_wake < MAX_UCHAR))
                {
-                       /* Hack -- Count the wakings */
-                       if ((r_ptr->r_wake < MAX_UCHAR) && is_original_ap(m_ptr))
-                       {
-                               r_ptr->r_wake++;
-                       }
+                       r_ptr->r_wake++;
                }
        }
 
@@ -2829,6 +2809,7 @@ msg_format("%^s%s", m_name, monmessage);
        do_turn = FALSE;
        do_move = FALSE;
        do_view = FALSE;
+       must_alter_to_move = FALSE;
 
        /* Assume nothing */
        did_open_door = FALSE;
@@ -2870,12 +2851,26 @@ msg_format("%^s%s", m_name, monmessage);
                        do_move = TRUE;
                }
 
+               /* Possibly a monster to attack */
                else if (c_ptr->m_idx)
                {
-                       /* Possibly a monster to attack */
                        do_move = TRUE;
                }
 
+               /* Monster destroys walls (and doors) */
+               else if ((r_ptr->flags2 & RF2_KILL_WALL) &&
+                        (can_cross ? !have_flag(f_ptr->flags, FF_LOS) : !is_riding_mon) &&
+                        have_flag(f_ptr->flags, FF_HURT_DISI) && !have_flag(f_ptr->flags, FF_PERMANENT) &&
+                        check_hp_for_feat_destruction(f_ptr, m_ptr))
+               {
+                       /* Eat through walls/doors/rubble */
+                       do_move = TRUE;
+                       if (!can_cross) must_alter_to_move = TRUE;
+
+                       /* Monster destroyed a wall (later) */
+                       did_kill_wall = TRUE;
+               }
+
                /* Floor is open? */
                else if (can_cross)
                {
@@ -2889,31 +2884,12 @@ msg_format("%^s%s", m_name, monmessage);
                                /* Monster went through a wall */
                                did_pass_wall = TRUE;
                        }
-
-                       if ((r_ptr->flags2 & RF2_KILL_WALL) && have_flag(f_ptr->flags, FF_TUNNEL) &&
-                           !have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_PERMANENT))
-                       {
-                               /* Monster destroyed a wall (later) */
-                               did_kill_wall = TRUE;
-                       }
-               }
-
-               /* Monster destroys walls (and doors) */
-               else if ((r_ptr->flags2 & RF2_KILL_WALL) && !is_riding_mon &&
-                        have_flag(f_ptr->flags, FF_TUNNEL) && !have_flag(f_ptr->flags, FF_PERMANENT))
-               {
-                       /* Eat through walls/doors/rubble */
-                       do_move = TRUE;
-
-                       /* Monster destroyed a wall (later) */
-                       did_kill_wall = TRUE;
                }
 
                /* Handle doors and secret doors */
                else if (is_closed_door(c_ptr->feat))
                {
                        bool may_bash = TRUE;
-                       feature_type *f_ptr = &f_info[c_ptr->feat];
 
                        /* Assume no move allowed */
                        do_move = FALSE;
@@ -2958,13 +2934,20 @@ msg_format("%^s%s", m_name, monmessage);
                                (!is_pet(m_ptr) || (p_ptr->pet_extra_flags & PF_OPEN_DOORS)))
                        {
                                /* Attempt to Bash XXX XXX XXX */
-                               if (randint0(m_ptr->hp / 10) > f_ptr->power)
+                               if (check_hp_for_feat_destruction(f_ptr, m_ptr) && (randint0(m_ptr->hp / 10) > f_ptr->power))
                                {
                                        /* Message */
+                                       if (have_flag(f_ptr->flags, FF_GLASS))
 #ifdef JP
-                                       msg_print("¥É¥¢¤ò᤭³«¤±¤ë²»¤¬¤·¤¿¡ª");
+                                               msg_print("¥¬¥é¥¹¤¬ºÕ¤±¤ë²»¤¬¤·¤¿¡ª");
 #else
-                                       msg_print("You hear a door burst open!");
+                                               msg_print("You hear a glass was crashed!");
+#endif
+                                       else
+#ifdef JP
+                                               msg_print("¥É¥¢¤ò᤭³«¤±¤ë²»¤¬¤·¤¿¡ª");
+#else
+                                               msg_print("You hear a door burst open!");
 #endif
 
                                        /* Disturb (sometimes) */
@@ -2975,6 +2958,7 @@ msg_format("%^s%s", m_name, monmessage);
 
                                        /* Hack -- fall into doorway */
                                        do_move = TRUE;
+                                       must_alter_to_move = TRUE;
                                }
                        }
 
@@ -2983,9 +2967,19 @@ msg_format("%^s%s", m_name, monmessage);
                        if (did_open_door || did_bash_door)
                        {
                                /* Break down the door */
-                               if (did_bash_door && ((randint0(100) < 50) || (feat_state(c_ptr->feat, FF_OPEN) == c_ptr->feat)))
+                               if (did_bash_door && ((randint0(100) < 50) || (feat_state(c_ptr->feat, FF_OPEN) == c_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)))
                                {
                                        cave_alter_feat(ny, nx, FF_BASH);
+
+                                       if (!m_ptr->r_idx) /* Killed by shards of glass, etc. */
+                                       {
+                                               /* Update some things */
+                                               p_ptr->update |= (PU_FLOW);
+                                               p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
+                                               if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
+
+                                               return;
+                                       }
                                }
 
                                /* Open the door */
@@ -2994,6 +2988,8 @@ msg_format("%^s%s", m_name, monmessage);
                                        cave_alter_feat(ny, nx, FF_OPEN);
                                }
 
+                               f_ptr = &f_info[c_ptr->feat];
+
                                /* Handle viewable doors */
                                do_view = TRUE;
                        }
@@ -3184,6 +3180,59 @@ msg_format("%^s%s", m_name, monmessage);
                        }
                }
 
+               if (is_riding_mon)
+               {
+                       if (!p_ptr->riding_ryoute && !MON_MONFEAR(&m_list[p_ptr->riding])) do_move = FALSE;
+               }
+
+               if (did_kill_wall && do_move)
+               {
+                       if (one_in_(GRINDNOISE))
+                       {
+                               if (have_flag(f_ptr->flags, FF_GLASS))
+#ifdef JP
+                                       msg_print("²¿¤«¤ÎºÕ¤±¤ë²»¤¬Ê¹¤³¤¨¤ë¡£");
+#else
+                                       msg_print("There is a crashing sound.");
+#endif
+                               else
+#ifdef JP
+                                       msg_print("¥®¥·¥®¥·¤¤¤¦²»¤¬Ê¹¤³¤¨¤ë¡£");
+#else
+                                       msg_print("There is a grinding sound.");
+#endif
+                       }
+
+                       cave_alter_feat(ny, nx, FF_HURT_DISI);
+
+                       if (!m_ptr->r_idx) /* Killed by shards of glass, etc. */
+                       {
+                               /* Update some things */
+                               p_ptr->update |= (PU_FLOW);
+                               p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
+                               if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flags2 |= (RF2_KILL_WALL);
+
+                               return;
+                       }
+
+                       f_ptr = &f_info[c_ptr->feat];
+
+                       /* Note changes to viewable region */
+                       do_view = TRUE;
+
+                       /* Take a turn */
+                       do_turn = TRUE;
+               }
+
+               if (must_alter_to_move && (r_ptr->flags7 & RF7_AQUATIC))
+               {
+                       if (!monster_can_cross_terrain(c_ptr->feat, r_ptr, is_riding_mon ? CEM_RIDING : 0))
+                       {
+                               /* Assume no move allowed */
+                               do_move = FALSE;
+                       }
+               }
+
                /*
                 * Check if monster can cross terrain
                 * This is checked after the normal attacks
@@ -3199,18 +3248,13 @@ msg_format("%^s%s", m_name, monmessage);
                /* Some monsters never move */
                if (do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
                {
-                       /* Hack -- memorize lack of attacks */
+                       /* Hack -- memorize lack of moves */
                        if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flags1 |= (RF1_NEVER_MOVE);
 
                        /* Do not move */
                        do_move = FALSE;
                }
 
-               if (is_riding_mon)
-               {
-                       if (!p_ptr->riding_ryoute && !MON_MONFEAR(&m_list[p_ptr->riding])) do_move = FALSE;
-               }
-
                /* Creature has been allowed move */
                if (do_move)
                {
@@ -3219,25 +3263,9 @@ msg_format("%^s%s", m_name, monmessage);
                        /* Take a turn */
                        do_turn = TRUE;
 
-                       if (did_kill_wall)
+                       if (have_flag(f_ptr->flags, FF_TREE))
                        {
-                               if (one_in_(GRINDNOISE))
-                               {
-#ifdef JP
-                                       msg_print("¥®¥·¥®¥·¤¤¤¦²»¤¬Ê¹¤³¤¨¤ë¡£");
-#else
-                                       msg_print("There is a grinding sound.");
-#endif
-                               }
-
-                               cave_alter_feat(ny, nx, FF_HURT_DISI);
-
-                               /* Note changes to viewable region */
-                               do_view = TRUE;
-                       }
-                       else if (have_flag(f_ptr->flags, FF_TREE))
-                       {
-                               if (!(r_ptr->flags7 & RF7_CAN_FLY) && (!is_riding_mon || !p_ptr->levitation) && !(r_ptr->flags8 & RF8_WILD_WOOD))
+                               if (!(r_ptr->flags7 & RF7_CAN_FLY) && !(r_ptr->flags8 & RF8_WILD_WOOD))
                                {
                                        m_ptr->energy_need += ENERGY_NEED();
                                }
@@ -3287,7 +3315,7 @@ msg_format("%^s%s", m_name, monmessage);
                        /* Possible disturb */
                        if (m_ptr->ml &&
                            (disturb_move ||
-                            (disturb_near && (m_ptr->mflag & MFLAG_VIEW)) ||
+                            (disturb_near && (m_ptr->mflag & MFLAG_VIEW) && projectable(py, px, m_ptr->fy, m_ptr->fx)) ||
                             (disturb_high && ap_r_ptr->r_tkills && ap_r_ptr->level >= p_ptr->lev)))
                        {
                                /* Disturb */
@@ -3917,7 +3945,7 @@ bool set_monster_fast(int m_idx, int v)
 
        if (!notice) return FALSE;
 
-       if (p_ptr->riding == m_idx) p_ptr->update |= (PU_BONUS);
+       if ((p_ptr->riding == m_idx) && !p_ptr->leaving) p_ptr->update |= (PU_BONUS);
 
        return TRUE;
 }
@@ -3959,7 +3987,7 @@ bool set_monster_slow(int m_idx, int v)
 
        if (!notice) return FALSE;
 
-       if (p_ptr->riding == m_idx) p_ptr->update |= (PU_BONUS);
+       if ((p_ptr->riding == m_idx) && !p_ptr->leaving) p_ptr->update |= (PU_BONUS);
 
        return TRUE;
 }
@@ -4582,14 +4610,33 @@ void monster_gain_exp(int m_idx, int s_idx)
                {
                        if (!ignore_unview || player_can_see_bold(m_ptr->fy, m_ptr->fx))
                        {
+                               if (p_ptr->image)
+                               {
+                                       monster_race *hallu_race;
+
+                                       do
+                                       {
+                                               hallu_race = &r_info[randint1(max_r_idx - 1)];
+                                       }
+                                       while (!hallu_race->name || (hallu_race->flags1 & RF1_UNIQUE));
+
 #ifdef JP
-                               msg_format("%s¤Ï%s¤Ë¿Ê²½¤·¤¿¡£", m_name, r_name + r_ptr->name);
+                                       msg_format("%s¤Ï%s¤Ë¿Ê²½¤·¤¿¡£", m_name, r_name + hallu_race->name);
 #else
-                               msg_format("%^s evolved into %s.", m_name, r_name + r_ptr->name);
+                                       msg_format("%^s evolved into %s.", m_name, r_name + hallu_race->name);
 #endif
+                               }
+                               else
+                               {
+#ifdef JP
+                                       msg_format("%s¤Ï%s¤Ë¿Ê²½¤·¤¿¡£", m_name, r_name + r_ptr->name);
+#else
+                                       msg_format("%^s evolved into %s.", m_name, r_name + r_ptr->name);
+#endif
+                               }
                        }
 
-                       r_info[old_r_idx].r_xtra1 |= MR1_SINKA;
+                       if (!p_ptr->image) r_info[old_r_idx].r_xtra1 |= MR1_SINKA;
 
                        /* Now you feel very close to this pet. */
                        m_ptr->parent_m_idx = 0;