}
-/*!
- * @brief モンスターから敵モンスターへの命中判定
- * @param power 打撃属性による基本命中値
- * @param level 攻撃側モンスターのレベル
- * @param ac 目標モンスターのAC
- * @param stun 攻撃側モンスターが朦朧状態ならTRUEを返す
- * @return 命中ならばTRUEを返す
- */
-static int check_hit2(int power, DEPTH level, ARMOUR_CLASS ac, int stun)
-{
- int i, k;
-
- /* Percentile dice */
- k = randint0(100);
-
- if (stun && one_in_(2)) return FALSE;
-
- /* Hack -- Always miss or hit */
- if (k < 10) return (k < 5);
-
- /* Calculate the "attack quality" */
- i = (power + (level * 3));
-
- /* Power and Level compete against Armor */
- if ((i > 0) && (randint1(i) > ((ac * 3) / 4))) return (TRUE);
-
- /* Assume miss */
- return (FALSE);
-}
-
-
-#define BLOW_EFFECT_TYPE_NONE 0
-#define BLOW_EFFECT_TYPE_FEAR 1
-#define BLOW_EFFECT_TYPE_SLEEP 2
-#define BLOW_EFFECT_TYPE_HEAL 3
-
-
-/*!
- * @brief モンスターから敵モンスターへの打撃攻撃処理
- * @param m_idx 攻撃側モンスターの参照ID
- * @param t_idx 目標側モンスターの参照ID
- * @return 実際に打撃処理が行われた場合TRUEを返す
- */
-static bool monst_attack_monst(MONSTER_IDX m_idx, MONSTER_IDX t_idx)
-{
- monster_type *m_ptr = ¤t_floor_ptr->m_list[m_idx];
- monster_type *t_ptr = ¤t_floor_ptr->m_list[t_idx];
-
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- monster_race *tr_ptr = &r_info[t_ptr->r_idx];
-
- ARMOUR_CLASS ap_cnt;
- ARMOUR_CLASS ac;
- DEPTH rlev;
- int pt;
- GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
- char temp[MAX_NLEN];
- bool blinked;
- bool explode = FALSE, touched = FALSE, fear = FALSE, dead = FALSE;
- POSITION y_saver = t_ptr->fy;
- POSITION x_saver = t_ptr->fx;
- int effect_type;
-
- bool see_m = is_seen(m_ptr);
- bool see_t = is_seen(t_ptr);
- bool see_either = see_m || see_t;
-
- /* Can the player be aware of this attack? */
- bool known = (m_ptr->cdis <= MAX_SIGHT) || (t_ptr->cdis <= MAX_SIGHT);
- bool do_silly_attack = (one_in_(2) && p_ptr->image);
-
- /* Cannot attack self */
- if (m_idx == t_idx) return FALSE;
-
- /* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return FALSE;
-
- if (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) return (FALSE);
-
- /* Total armor */
- ac = tr_ptr->ac;
-
- /* Extract the effective monster level */
- rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
-
- monster_desc(m_name, m_ptr, 0);
- monster_desc(t_name, t_ptr, 0);
-
- /* Assume no blink */
- blinked = FALSE;
-
- if (!see_either && known)
- {
- current_floor_ptr->monster_noise = TRUE;
- }
-
- if (p_ptr->riding && (m_idx == p_ptr->riding)) disturb(TRUE, TRUE);
-
- /* Scan through all four blows */
- for (ap_cnt = 0; ap_cnt < 4; ap_cnt++)
- {
- bool obvious = FALSE;
-
- HIT_POINT power = 0;
- HIT_POINT damage = 0;
-
- concptr act = NULL;
-
- /* Extract the attack infomation */
- int effect = r_ptr->blow[ap_cnt].effect;
- int method = r_ptr->blow[ap_cnt].method;
- int d_dice = r_ptr->blow[ap_cnt].d_dice;
- int d_side = r_ptr->blow[ap_cnt].d_side;
-
- if (!monster_is_valid(m_ptr)) break;
-
- /* Stop attacking if the target dies! */
- if (t_ptr->fx != x_saver || t_ptr->fy != y_saver)
- break;
-
- /* Hack -- no more attacks */
- if (!method) break;
-
- if (method == RBM_SHOOT) continue;
-
- /* Extract the attack "power" */
- power = mbe_info[effect].power;
-
- /* Monster hits */
- if (!effect || check_hit2(power, rlev, ac, MON_STUNNED(m_ptr)))
- {
- (void)set_monster_csleep(t_idx, 0);
-
- if (t_ptr->ml)
- {
- /* Redraw the health bar */
- if (p_ptr->health_who == t_idx) p_ptr->redraw |= (PR_HEALTH);
- if (p_ptr->riding == t_idx) p_ptr->redraw |= (PR_UHEALTH);
- }
-
- /* Describe the attack method */
- switch (method)
- {
- case RBM_HIT:
- {
- act = _("%sを殴った。", "hits %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_TOUCH:
- {
- act = _("%sを触った。", "touches %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_PUNCH:
- {
- act = _("%sをパンチした。", "punches %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_KICK:
- {
- act = _("%sを蹴った。", "kicks %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_CLAW:
- {
- act = _("%sをひっかいた。", "claws %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_BITE:
- {
- act = _("%sを噛んだ。", "bites %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_STING:
- {
- act = _("%sを刺した。", "stings %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_SLASH:
- {
- act = _("%sを斬った。", "slashes %s.");
- break;
- }
-
- case RBM_BUTT:
- {
- act = _("%sを角で突いた。", "butts %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_CRUSH:
- {
- act = _("%sに体当りした。", "crushes %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_ENGULF:
- {
- act = _("%sを飲み込んだ。", "engulfs %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_CHARGE:
- {
- act = _("%sに請求書をよこした。", "charges %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_CRAWL:
- {
- act = _("%sの体の上を這い回った。", "crawls on %s.");
- touched = TRUE;
- break;
- }
-
- case RBM_DROOL:
- {
- act = _("%sによだれをたらした。", "drools on %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_SPIT:
- {
- act = _("%sに唾を吐いた。", "spits on %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_EXPLODE:
- {
- if (see_either) disturb(TRUE, TRUE);
- act = _("爆発した。", "explodes.");
- explode = TRUE;
- touched = FALSE;
- break;
- }
-
- case RBM_GAZE:
- {
- act = _("%sをにらんだ。", "gazes at %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_WAIL:
- {
- act = _("%sに泣きついた。", "wails at %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_SPORE:
- {
- act = _("%sに胞子を飛ばした。", "releases spores at %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_XXX4:
- {
- act = _("%sにXXX4を飛ばした。", "projects XXX4's at %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_BEG:
- {
- act = _("%sに金をせがんだ。", "begs %s for money.");
- touched = FALSE;
- break;
- }
-
- case RBM_INSULT:
- {
- act = _("%sを侮辱した。", "insults %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_MOAN:
- {
- act = _("%sにむかってうめいた。", "moans at %s.");
- touched = FALSE;
- break;
- }
-
- case RBM_SHOW:
- {
- act = _("%sにむかって歌った。", "sings to %s.");
- touched = FALSE;
- break;
- }
- }
-
- if (act && see_either)
- {
-#ifdef JP
- if (do_silly_attack) act = silly_attacks2[randint0(MAX_SILLY_ATTACK)];
- strfmt(temp, act, t_name);
- msg_format("%^sは%s", m_name, temp);
-#else
- if (do_silly_attack)
- {
- act = silly_attacks[randint0(MAX_SILLY_ATTACK)];
- strfmt(temp, "%s %s.", act, t_name);
- }
- else strfmt(temp, act, t_name);
- msg_format("%^s %s", m_name, temp);
-#endif
- }
-
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
- /* Roll out the damage */
- damage = damroll(d_dice, d_side);
-
- /* Assume no effect */
- effect_type = BLOW_EFFECT_TYPE_NONE;
-
- pt = GF_MISSILE;
-
- /* Apply appropriate damage */
- switch (effect)
- {
- case 0:
- case RBE_DR_MANA:
- damage = pt = 0;
- break;
-
- case RBE_SUPERHURT:
- 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;
- }
-
- /* Fall through */
-
- case RBE_HURT:
- damage -= (damage * ((ac < 150) ? ac : 150) / 250);
- break;
-
- case RBE_POISON:
- case RBE_DISEASE:
- pt = GF_POIS;
- break;
-
- case RBE_UN_BONUS:
- case RBE_UN_POWER:
- pt = GF_DISENCHANT;
- break;
-
- case RBE_EAT_ITEM:
- case RBE_EAT_GOLD:
- 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;
-
- case RBE_ELEC:
- pt = GF_ELEC;
- break;
-
- case RBE_FIRE:
- pt = GF_FIRE;
- break;
-
- case RBE_COLD:
- pt = GF_COLD;
- break;
-
- case RBE_CONFUSE:
- pt = GF_CONFUSION;
- break;
-
- case RBE_TERRIFY:
- effect_type = BLOW_EFFECT_TYPE_FEAR;
- break;
-
- case RBE_PARALYZE:
- effect_type = BLOW_EFFECT_TYPE_SLEEP;
- break;
-
- case RBE_SHATTER:
- damage -= (damage * ((ac < 150) ? ac : 150) / 250);
- if (damage > 23) earthquake(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;
-
- case RBE_TIME:
- pt = GF_TIME;
- break;
-
- case RBE_DR_LIFE:
- pt = GF_HYPODYNAMIA;
- effect_type = BLOW_EFFECT_TYPE_HEAL;
- break;
-
- case RBE_INERTIA:
- pt = GF_INERTIAL;
- break;
-
- case RBE_STUN:
- pt = GF_SOUND;
- break;
-
- default:
- pt = 0;
- break;
- }
-
- if (pt)
- {
- /* Do damage if not exploding */
- if (!explode)
- {
- project(m_idx, 0, t_ptr->fy, t_ptr->fx,
- damage, pt, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
- }
-
- 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(m_idx)) && (damage > 2))
- {
- bool did_heal = FALSE;
-
- if (m_ptr->hp < m_ptr->maxhp) did_heal = TRUE;
-
- /* Heal */
- m_ptr->hp += damroll(4, damage / 6);
- if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
-
- /* Redraw (later) if needed */
- if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
- if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
-
- /* Special message */
- if (see_m && did_heal)
- {
- msg_format(_("%sは体力を回復したようだ。", "%^s appears healthier."), m_name);
- }
- }
- break;
- }
-
- if (touched)
- {
- /* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) && m_ptr->r_idx)
- {
- if (!(r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK))
- {
- if (see_either)
- {
- msg_format(_("%^sは突然熱くなった!", "%^s is suddenly very hot!"), m_name);
- }
- if (m_ptr->ml && is_original_ap_and_seen(t_ptr)) tr_ptr->r_flags2 |= RF2_AURA_FIRE;
- project(t_idx, 0, m_ptr->fy, m_ptr->fx,
- damroll (1 + ((tr_ptr->level) / 26),
- 1 + ((tr_ptr->level) / 17)),
- GF_FIRE, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
- }
- else
- {
- if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK);
- }
- }
-
- /* Aura cold */
- if ((tr_ptr->flags3 & RF3_AURA_COLD) && m_ptr->r_idx)
- {
- if (!(r_ptr->flagsr & RFR_EFF_IM_COLD_MASK))
- {
- if (see_either)
- {
- msg_format(_("%^sは突然寒くなった!", "%^s is suddenly very cold!"), m_name);
- }
- if (m_ptr->ml && is_original_ap_and_seen(t_ptr)) tr_ptr->r_flags3 |= RF3_AURA_COLD;
- project(t_idx, 0, m_ptr->fy, m_ptr->fx,
- damroll (1 + ((tr_ptr->level) / 26),
- 1 + ((tr_ptr->level) / 17)),
- GF_COLD, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
- }
- else
- {
- if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK);
- }
- }
-
- /* Aura elec */
- if ((tr_ptr->flags2 & RF2_AURA_ELEC) && m_ptr->r_idx)
- {
- if (!(r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK))
- {
- if (see_either)
- {
- msg_format(_("%^sは電撃を食らった!", "%^s gets zapped!"), m_name);
- }
- if (m_ptr->ml && is_original_ap_and_seen(t_ptr)) tr_ptr->r_flags2 |= RF2_AURA_ELEC;
- project(t_idx, 0, m_ptr->fy, m_ptr->fx,
- damroll (1 + ((tr_ptr->level) / 26),
- 1 + ((tr_ptr->level) / 17)),
- GF_ELEC, PROJECT_KILL | PROJECT_STOP | PROJECT_AIMED, -1);
- }
- else
- {
- if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK);
- }
- }
- }
- }
- }
-
- /* Monster missed player */
- else
- {
- /* Analyze failed attacks */
- switch (method)
- {
- case RBM_HIT:
- case RBM_TOUCH:
- case RBM_PUNCH:
- case RBM_KICK:
- case RBM_CLAW:
- case RBM_BITE:
- case RBM_STING:
- case RBM_SLASH:
- case RBM_BUTT:
- case RBM_CRUSH:
- case RBM_ENGULF:
- case RBM_CHARGE:
- {
- (void)set_monster_csleep(t_idx, 0);
-
- /* Visible monsters */
- if (see_m)
- {
-#ifdef JP
- msg_format("%sは%^sの攻撃をかわした。", t_name, m_name);
-#else
- msg_format("%^s misses %s.", m_name, t_name);
-#endif
- }
-
- break;
- }
- }
- }
-
-
- /* Analyze "visible" monsters only */
- if (is_original_ap_and_seen(m_ptr) && !do_silly_attack)
- {
- /* Count "obvious" attacks (and ones that cause damage) */
- if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10))
- {
- /* Count attacks of this type */
- if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR)
- {
- r_ptr->r_blows[ap_cnt]++;
- }
- }
- }
- }
-
- if (explode)
- {
- sound(SOUND_EXPLODE);
-
- /* Cancel Invulnerability */
- (void)set_monster_invulner(m_idx, 0, FALSE);
- mon_take_hit_mon(m_idx, m_ptr->hp + 1, &dead, &fear, _("は爆発して粉々になった。", " explodes into tiny shreds."), m_idx);
- blinked = FALSE;
- }
-
- /* Blink away */
- if (blinked && m_ptr->r_idx)
- {
- if (teleport_barrier(m_idx))
- {
- if (see_m)
- {
- msg_print(_("泥棒は笑って逃げ...ようとしたがバリアに防がれた。", "The thief flees laughing...? But magic barrier obstructs it."));
- }
- else if (known)
- {
- current_floor_ptr->monster_noise = TRUE;
- }
- }
- else
- {
- if (see_m)
- {
- msg_print(_("泥棒は笑って逃げた!", "The thief flees laughing!"));
- }
- else if (known)
- {
- current_floor_ptr->monster_noise = TRUE;
- }
-
- 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) ||