1 #include "monster/monster-status.h"
2 #include "autopick/autopick-pref-processor.h"
3 #include "cmd-io/cmd-dump.h"
4 #include "core/player-redraw-types.h"
5 #include "core/player-update-types.h"
6 #include "core/speed-table.h"
7 #include "core/stuff-handler.h"
8 #include "dungeon/dungeon-flag-types.h"
9 #include "dungeon/dungeon.h"
10 #include "floor/cave.h"
11 #include "game-option/birth-options.h"
12 #include "game-option/play-record-options.h"
13 #include "game-option/text-display-options.h"
14 #include "grid/grid.h"
15 #include "io/files-util.h"
16 #include "io/report.h"
17 #include "io/write-diary.h"
18 #include "main/sound-definitions-table.h"
19 #include "main/sound-of-music.h"
20 #include "mind/mind-ninja.h"
21 #include "monster-attack/monster-attack-effect.h"
22 #include "monster-attack/monster-attack-types.h"
23 #include "monster-floor/monster-death.h"
24 #include "monster-floor/monster-remover.h"
25 #include "monster-floor/monster-summon.h"
26 #include "monster-floor/place-monster-types.h"
27 #include "monster-race/monster-race-hook.h"
28 #include "monster-race/monster-race.h"
29 #include "monster-race/race-flags-ability2.h"
30 #include "monster-race/race-flags-resistance.h"
31 #include "monster-race/race-flags1.h"
32 #include "monster-race/race-flags2.h"
33 #include "monster-race/race-flags3.h"
34 #include "monster-race/race-flags4.h"
35 #include "monster-race/race-flags7.h"
36 #include "monster-race/race-flags8.h"
37 #include "monster-race/race-indice-types.h"
38 #include "monster/monster-describer.h"
39 #include "monster/monster-description-types.h"
40 #include "monster/monster-flag-types.h"
41 #include "monster/monster-info.h"
42 #include "monster/monster-list.h"
43 #include "monster/monster-status-setter.h" // todo 相互依存. 後で何とかする.
44 #include "monster/monster-update.h"
45 #include "monster/smart-learn-types.h"
46 #include "mspell/mspell-mask-definitions.h"
47 #include "object-enchant/object-curse.h"
48 #include "player-info/avatar.h"
49 #include "player/player-personalities-types.h"
50 #include "player/special-defense-types.h"
51 #include "spell-kind/spells-random.h"
52 #include "spell/spells-summon.h"
53 #include "status/experience.h"
54 #include "system/floor-type-definition.h"
55 #include "view/display-messages.h"
56 #include "world/world.h"
59 * @brief モンスターIDからPOWERFULフラグの有無を取得する /
60 * @param floor_ptr 現在フロアへの参照ポインタ
61 * @param m_idx モンスターID
62 * @return POWERFULフラグがあればTRUE、なければFALSEを返す。
64 bool monster_is_powerful(floor_type *floor_ptr, MONSTER_IDX m_idx)
66 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
67 monster_race *r_ptr = &r_info[m_ptr->r_idx];
68 bool powerful = r_ptr->flags2 & RF2_POWERFUL ? TRUE : FALSE;
73 * @brief モンスターIDからモンスターのレベルを取得する(ただし最低1を保証する) /
74 * @param m_idx モンスターID
77 DEPTH monster_level_idx(floor_type *floor_ptr, MONSTER_IDX m_idx)
79 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
80 monster_race *r_ptr = &r_info[m_ptr->r_idx];
81 DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
86 * @brief モンスターに与えたダメージの修正処理 /
87 * Modify the physical damage done to the monster.
88 * @param target_ptr プレーヤーへの参照ポインタ
89 * @param m_ptr ダメージを受けるモンスターの構造体参照ポインタ
91 * @param is_psy_spear 攻撃手段が光の剣ならばTRUE
92 * @return 修正を行った結果のダメージ量
95 * (for example when it's invulnerable or shielded)
96 * ToDo: Accept a damage-type to calculate the modified damage from
97 * things like fire, frost, lightning, poison, ... attacks.
98 * "type" is not yet used and should be 0.
101 HIT_POINT mon_damage_mod(player_type *target_ptr, monster_type *m_ptr, HIT_POINT dam, bool is_psy_spear)
103 monster_race *r_ptr = &r_info[m_ptr->r_idx];
105 if ((r_ptr->flagsr & RFR_RES_ALL) && dam > 0) {
107 if ((dam == 0) && one_in_(3))
111 if (monster_invulner_remaining(m_ptr)) {
113 if (!target_ptr->blind && is_seen(target_ptr, m_ptr)) {
114 msg_print(_("バリアを切り裂いた!", "The barrier is penetrated!"));
116 } else if (!one_in_(PENETRATE_INVULNERABILITY)) {
125 * @brief モンスターに与えたダメージを元に経験値を加算する /
126 * Calculate experience point to be get
127 * @param dam 与えたダメージ量
128 * @param m_ptr ダメージを与えたモンスターの構造体参照ポインタ
132 * Even the 64 bit operation is not big enough to avoid overflaw
133 * unless we carefully choose orders of multiplication and division.
134 * Get the coefficient first, and multiply (potentially huge) base
135 * experience point of a monster later.
138 static void get_exp_from_mon(player_type *target_ptr, HIT_POINT dam, monster_type *m_ptr)
140 monster_race *r_ptr = &r_info[m_ptr->r_idx];
142 if (!monster_is_valid(m_ptr))
144 if (is_pet(m_ptr) || target_ptr->phase_out)
148 * todo 変数宣言と代入を同時に実行するとコンパイル警告が出る
157 * - Ratio of monster's level to player's level effects
158 * - Varying speed effects
159 * - Get a fraction in proportion of damage point
161 new_exp = r_ptr->level * SPEED_TO_ENERGY(m_ptr->mspeed) * dam;
164 div_l = (target_ptr->max_plv + 2) * SPEED_TO_ENERGY(r_ptr->speed);
166 /* Use (average maxhp * 2) as a denominator */
167 if (!(r_ptr->flags1 & RF1_FORCE_MAXHP))
168 s64b_mul(&div_h, &div_l, 0, r_ptr->hdice * (ironman_nightmare ? 2 : 1) * (r_ptr->hside + 1));
170 s64b_mul(&div_h, &div_l, 0, r_ptr->hdice * (ironman_nightmare ? 2 : 1) * r_ptr->hside * 2);
172 /* Special penalty in the wilderness */
173 if (!target_ptr->current_floor_ptr->dun_level && (!(r_ptr->flags8 & RF8_WILD_ONLY) || !(r_ptr->flags1 & RF1_UNIQUE)))
174 s64b_mul(&div_h, &div_l, 0, 5);
176 /* Do division first to prevent overflaw */
177 s64b_div(&new_exp, &new_exp_frac, div_h, div_l);
179 /* Special penalty for mutiply-monster */
180 if ((r_ptr->flags2 & RF2_MULTIPLY) || (m_ptr->r_idx == MON_DAWN)) {
181 int monnum_penarty = r_ptr->r_akills / 400;
182 if (monnum_penarty > 8)
185 while (monnum_penarty--) {
187 s64b_RSHIFT(new_exp, new_exp_frac, 2);
191 /* Special penalty for rest_and_shoot exp scum */
192 if ((m_ptr->dealt_damage > m_ptr->max_maxhp) && (m_ptr->hp >= 0)) {
193 int over_damage = m_ptr->dealt_damage / m_ptr->max_maxhp;
194 if (over_damage > 32)
197 while (over_damage--) {
199 s64b_mul(&new_exp, &new_exp_frac, 0, 9);
200 s64b_div(&new_exp, &new_exp_frac, 0, 10);
204 s64b_mul(&new_exp, &new_exp_frac, 0, r_ptr->mexp);
205 gain_exp_64(target_ptr, new_exp, new_exp_frac);
209 * @brief モンスターの時限ステータスを取得する
210 * @param floor_ptr 現在フロアへの参照ポインタ
211 * @return m_idx モンスターの参照ID
212 * @return mproc_type モンスターの時限ステータスID
215 int get_mproc_idx(floor_type *floor_ptr, MONSTER_IDX m_idx, int mproc_type)
217 s16b *cur_mproc_list = floor_ptr->mproc_list[mproc_type];
218 for (int i = floor_ptr->mproc_max[mproc_type] - 1; i >= 0; i--) {
219 if (cur_mproc_list[i] == m_idx)
227 * @brief モンスターの時限ステータスリストを追加する
228 * @param floor_ptr 現在フロアへの参照ポインタ
229 * @return m_idx モンスターの参照ID
230 * @return mproc_type 追加したいモンスターの時限ステータスID
233 void mproc_add(floor_type *floor_ptr, MONSTER_IDX m_idx, int mproc_type)
235 if (floor_ptr->mproc_max[mproc_type] < current_world_ptr->max_m_idx) {
236 floor_ptr->mproc_list[mproc_type][floor_ptr->mproc_max[mproc_type]++] = (s16b)m_idx;
241 * @brief モンスターの時限ステータスリストを初期化する / Initialize monster process
242 * @param floor_ptr 現在フロアへの参照ポインタ
245 void mproc_init(floor_type *floor_ptr)
247 /* Reset "target_ptr->current_floor_ptr->mproc_max[]" */
248 for (int i = 0; i < MAX_MTIMED; i++) {
249 floor_ptr->mproc_max[i] = 0;
252 /* Process the monsters (backwards) */
253 for (MONSTER_IDX i = floor_ptr->m_max - 1; i >= 1; i--) {
255 m_ptr = &floor_ptr->m_list[i];
257 /* Ignore "dead" monsters */
258 if (!monster_is_valid(m_ptr))
261 for (int cmi = 0; cmi < MAX_MTIMED; cmi++) {
262 if (m_ptr->mtimed[cmi])
263 mproc_add(floor_ptr, i, cmi);
268 static u32b csleep_noise;
271 * @brief モンスターの各種状態値を時間経過により更新するサブルーチン
272 * @param floor_ptr 現在フロアへの参照ポインタ
273 * @param m_idx モンスター参照ID
274 * @param mtimed_idx 更新するモンスターの時限ステータスID
277 static void process_monsters_mtimed_aux(player_type *target_ptr, MONSTER_IDX m_idx, int mtimed_idx)
279 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
281 switch (mtimed_idx) {
282 case MTIMED_CSLEEP: {
283 monster_race *r_ptr = &r_info[m_ptr->r_idx];
285 /* Assume does not wake up */
288 /* Hack -- Require proximity */
289 if (m_ptr->cdis < AAF_LIMIT) {
290 /* Handle "sensing radius" */
291 if (m_ptr->cdis <= (is_pet(m_ptr) ? ((r_ptr->aaf > MAX_SIGHT) ? MAX_SIGHT : r_ptr->aaf) : r_ptr->aaf)) {
296 /* Handle "sight" and "aggravation" */
297 else if ((m_ptr->cdis <= MAX_SIGHT) && (player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx))) {
306 u32b notice = randint0(1024);
308 /* Nightmare monsters are more alert */
309 if (ironman_nightmare)
312 /* Hack -- See if monster "notices" player */
313 if ((notice * notice * notice) > csleep_noise)
316 /* Hack -- amount of "waking" */
317 /* Wake up faster near the player */
318 int d = (m_ptr->cdis < AAF_LIMIT / 2) ? (AAF_LIMIT / m_ptr->cdis) : 1;
320 /* Hack -- amount of "waking" is affected by speed of player */
321 d = (d * SPEED_TO_ENERGY(target_ptr->pspeed)) / 10;
325 /* Monster wakes up "a little bit" */
328 if (!set_monster_csleep(target_ptr, m_idx, monster_csleep_remaining(m_ptr) - d)) {
329 /* Notice the "not waking up" */
330 if (is_original_ap_and_seen(target_ptr, m_ptr)) {
331 /* Hack -- Count the ignores */
332 if (r_ptr->r_ignore < MAX_UCHAR)
339 /* Notice the "waking up" */
341 GAME_TEXT m_name[MAX_NLEN];
342 monster_desc(target_ptr, m_name, m_ptr, 0);
343 msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
346 if (is_original_ap_and_seen(target_ptr, m_ptr)) {
347 /* Hack -- Count the wakings */
348 if (r_ptr->r_wake < MAX_UCHAR)
356 /* Reduce by one, note if expires */
357 if (set_monster_fast(target_ptr, m_idx, monster_fast_remaining(m_ptr) - 1)) {
358 if (is_seen(target_ptr, m_ptr)) {
359 GAME_TEXT m_name[MAX_NLEN];
360 monster_desc(target_ptr, m_name, m_ptr, 0);
361 msg_format(_("%^sはもう加速されていない。", "%^s is no longer fast."), m_name);
368 /* Reduce by one, note if expires */
369 if (set_monster_slow(target_ptr, m_idx, monster_slow_remaining(m_ptr) - 1)) {
370 if (is_seen(target_ptr, m_ptr)) {
371 GAME_TEXT m_name[MAX_NLEN];
372 monster_desc(target_ptr, m_name, m_ptr, 0);
373 msg_format(_("%^sはもう減速されていない。", "%^s is no longer slow."), m_name);
379 case MTIMED_STUNNED: {
380 int rlev = r_info[m_ptr->r_idx].level;
382 /* Recover from stun */
383 if (set_monster_stunned(target_ptr, m_idx, (randint0(10000) <= rlev * rlev) ? 0 : (monster_stunned_remaining(m_ptr) - 1))) {
384 /* Message if visible */
385 if (is_seen(target_ptr, m_ptr)) {
386 GAME_TEXT m_name[MAX_NLEN];
387 monster_desc(target_ptr, m_name, m_ptr, 0);
388 msg_format(_("%^sは朦朧状態から立ち直った。", "%^s is no longer stunned."), m_name);
395 case MTIMED_CONFUSED: {
396 /* Reduce the confusion */
397 if (!set_monster_confused(target_ptr, m_idx, monster_confused_remaining(m_ptr) - randint1(r_info[m_ptr->r_idx].level / 20 + 1)))
399 /* Message if visible */
400 if (is_seen(target_ptr, m_ptr)) {
401 GAME_TEXT m_name[MAX_NLEN];
402 monster_desc(target_ptr, m_name, m_ptr, 0);
403 msg_format(_("%^sは混乱から立ち直った。", "%^s is no longer confused."), m_name);
409 case MTIMED_MONFEAR: {
410 /* Reduce the fear */
411 if (!set_monster_monfear(target_ptr, m_idx, monster_fear_remaining(m_ptr) - randint1(r_info[m_ptr->r_idx].level / 20 + 1)))
415 if (is_seen(target_ptr, m_ptr)) {
416 GAME_TEXT m_name[MAX_NLEN];
421 /* Acquire the monster possessive */
422 monster_desc(target_ptr, m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
424 monster_desc(target_ptr, m_name, m_ptr, 0);
426 msg_format("%^sは勇気を取り戻した。", m_name);
428 msg_format("%^s recovers %s courage.", m_name, m_poss);
435 case MTIMED_INVULNER: {
436 /* Reduce by one, note if expires */
437 if (!set_monster_invulner(target_ptr, m_idx, monster_invulner_remaining(m_ptr) - 1, TRUE))
440 if (is_seen(target_ptr, m_ptr)) {
441 GAME_TEXT m_name[MAX_NLEN];
442 monster_desc(target_ptr, m_name, m_ptr, 0);
443 msg_format(_("%^sはもう無敵でない。", "%^s is no longer invulnerable."), m_name);
452 * @brief 全モンスターの各種状態値を時間経過により更新するメインルーチン
453 * @param mtimed_idx 更新するモンスターの時限ステータスID
454 * @param target_ptr プレーヤーへの参照ポインタ
457 * Process the counters of monsters (once per 10 game turns)\n
458 * These functions are to process monsters' counters same as player's.
460 void process_monsters_mtimed(player_type *target_ptr, int mtimed_idx)
462 floor_type *floor_ptr = target_ptr->current_floor_ptr;
463 s16b *cur_mproc_list = floor_ptr->mproc_list[mtimed_idx];
465 /* Hack -- calculate the "player noise" */
466 if (mtimed_idx == MTIMED_CSLEEP)
467 csleep_noise = (1L << (30 - target_ptr->skill_stl));
469 /* Process the monsters (backwards) */
470 for (int i = floor_ptr->mproc_max[mtimed_idx] - 1; i >= 0; i--) {
471 process_monsters_mtimed_aux(target_ptr, cur_mproc_list[i], mtimed_idx);
476 * @brief モンスターへの魔力消去処理
477 * @param target_ptr プレーヤーへの参照ポインタ
478 * @param m_idx 魔力消去を受けるモンスターの参照ID
481 void dispel_monster_status(player_type *target_ptr, MONSTER_IDX m_idx)
483 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
484 GAME_TEXT m_name[MAX_NLEN];
486 monster_desc(target_ptr, m_name, m_ptr, 0);
487 if (set_monster_invulner(target_ptr, m_idx, 0, TRUE)) {
489 msg_format(_("%sはもう無敵ではない。", "%^s is no longer invulnerable."), m_name);
492 if (set_monster_fast(target_ptr, m_idx, 0)) {
494 msg_format(_("%sはもう加速されていない。", "%^s is no longer fast."), m_name);
497 if (set_monster_slow(target_ptr, m_idx, 0)) {
499 msg_format(_("%sはもう減速されていない。", "%^s is no longer slow."), m_name);
504 * @brief モンスターの経験値取得処理
505 * @param target_ptr プレーヤーへの参照ポインタ
506 * @param m_idx 経験値を得るモンスターの参照ID
507 * @param s_idx 撃破されたモンスター種族の参照ID
510 void monster_gain_exp(player_type *target_ptr, MONSTER_IDX m_idx, MONRACE_IDX s_idx)
515 if (m_idx <= 0 || s_idx <= 0)
518 floor_type *floor_ptr = target_ptr->current_floor_ptr;
519 m_ptr = &floor_ptr->m_list[m_idx];
521 if (!monster_is_valid(m_ptr))
524 r_ptr = &r_info[m_ptr->r_idx];
525 s_ptr = &r_info[s_idx];
527 if (target_ptr->phase_out)
530 if (!r_ptr->next_exp)
533 int new_exp = s_ptr->mexp * s_ptr->level / (r_ptr->level + 2);
534 if (m_idx == target_ptr->riding)
535 new_exp = (new_exp + 1) / 2;
536 if (!floor_ptr->dun_level)
538 m_ptr->exp += new_exp;
539 if (m_ptr->mflag2 & MFLAG2_CHAMELEON)
542 if (m_ptr->exp < r_ptr->next_exp) {
543 if (m_idx == target_ptr->riding)
544 target_ptr->update |= PU_BONUS;
548 GAME_TEXT m_name[MAX_NLEN];
549 int old_hp = m_ptr->hp;
550 int old_maxhp = m_ptr->max_maxhp;
551 int old_r_idx = m_ptr->r_idx;
552 byte old_sub_align = m_ptr->sub_align;
554 /* Hack -- Reduce the racial counter of previous monster */
555 real_r_ptr(m_ptr)->cur_num--;
557 monster_desc(target_ptr, m_name, m_ptr, 0);
558 m_ptr->r_idx = r_ptr->next_r_idx;
560 /* Count the monsters on the level */
561 real_r_ptr(m_ptr)->cur_num++;
563 m_ptr->ap_r_idx = m_ptr->r_idx;
564 r_ptr = &r_info[m_ptr->r_idx];
566 if (r_ptr->flags1 & RF1_FORCE_MAXHP) {
567 m_ptr->max_maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
569 m_ptr->max_maxhp = damroll(r_ptr->hdice, r_ptr->hside);
571 if (ironman_nightmare) {
572 HIT_POINT hp = m_ptr->max_maxhp * 2L;
573 m_ptr->max_maxhp = MIN(30000, hp);
576 m_ptr->maxhp = m_ptr->max_maxhp;
577 m_ptr->hp = old_hp * m_ptr->maxhp / old_maxhp;
579 /* dealt damage is 0 at initial*/
580 m_ptr->dealt_damage = 0;
582 /* Extract the monster base speed */
583 m_ptr->mspeed = get_mspeed(floor_ptr, r_ptr);
585 /* Sub-alignment of a monster */
586 if (!is_pet(m_ptr) && !(r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)))
587 m_ptr->sub_align = old_sub_align;
589 m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
590 if (r_ptr->flags3 & RF3_EVIL)
591 m_ptr->sub_align |= SUB_ALIGN_EVIL;
592 if (r_ptr->flags3 & RF3_GOOD)
593 m_ptr->sub_align |= SUB_ALIGN_GOOD;
598 if (is_pet(m_ptr) || m_ptr->ml) {
599 if (!ignore_unview || player_can_see_bold(target_ptr, m_ptr->fy, m_ptr->fx)) {
600 if (target_ptr->image) {
601 monster_race *hallu_race;
604 hallu_race = &r_info[randint1(max_r_idx - 1)];
605 } while (!hallu_race->name || (hallu_race->flags1 & RF1_UNIQUE));
606 msg_format(_("%sは%sに進化した。", "%^s evolved into %s."), m_name, r_name + hallu_race->name);
608 msg_format(_("%sは%sに進化した。", "%^s evolved into %s."), m_name, r_name + r_ptr->name);
612 if (!target_ptr->image)
613 r_info[old_r_idx].r_xtra1 |= MR1_EVOLUTION;
615 /* Now you feel very close to this pet. */
616 m_ptr->parent_m_idx = 0;
619 update_monster(target_ptr, m_idx, FALSE);
620 lite_spot(target_ptr, m_ptr->fy, m_ptr->fx);
622 if (m_idx == target_ptr->riding)
623 target_ptr->update |= PU_BONUS;
627 * @brief モンスターのHPをダメージに応じて減算する /
628 * Decreases monsters hit points, handling monster death.
629 * @param dam 与えたダメージ量
630 * @param m_idx ダメージを与えたモンスターのID
631 * @param fear ダメージによってモンスターが恐慌状態に陥ったならばTRUEを返す
632 * @param note モンスターが倒された際の特別なメッセージ述語
636 * We return TRUE if the monster has been killed (and deleted).
637 * We announce monster death (using an optional "death message"
638 * if given, and a otherwise a generic killed/destroyed message).
639 * Only "physical attacks" can induce the "You have slain" message.
640 * Missile and Spell attacks will induce the "dies" message, or
641 * various "specialized" messages. Note that "You have destroyed"
642 * and "is destroyed" are synonyms for "You have slain" and "dies".
643 * Hack -- unseen monsters yield "You have killed it." message.
644 * Added fear (DGK) and check whether to print fear messages -CWS
645 * Made name, sex, and capitalization generic -BEN-
646 * As always, the "ghost" processing is a total hack.
647 * Hack -- we "delay" fear messages by passing around a "fear" flag.
648 * Consider decreasing monster experience over time, say,
649 * by using "(m_exp * m_lev * (m_lev)) / (p_lev * (m_lev + n_killed))"
650 * instead of simply "(m_exp * m_lev) / (p_lev)", to make the first
651 * monster worth more than subsequent monsters. This would also need
652 * to induce changes in the monster recall code.
655 bool mon_take_hit(player_type *target_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *fear, concptr note)
657 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
658 monster_race *r_ptr = &r_info[m_ptr->r_idx];
659 monster_type exp_mon;
661 /* Innocent until proven otherwise */
662 bool innocent = TRUE, thief = FALSE;
666 (void)COPY(&exp_mon, m_ptr, monster_type);
668 expdam = (m_ptr->hp > dam) ? dam : m_ptr->hp;
670 get_exp_from_mon(target_ptr, expdam, &exp_mon);
672 /* Genocided by chaos patron */
673 if (!monster_is_valid(m_ptr))
676 /* Redraw (later) if needed */
677 if (target_ptr->health_who == m_idx)
678 target_ptr->redraw |= (PR_HEALTH);
679 if (target_ptr->riding == m_idx)
680 target_ptr->redraw |= (PR_UHEALTH);
682 (void)set_monster_csleep(target_ptr, m_idx, 0);
684 /* Hack - Cancel any special player stealth magics. -LM- */
685 if (target_ptr->special_defense & NINJA_S_STEALTH) {
686 set_superstealth(target_ptr, FALSE);
689 /* Genocided by chaos patron */
694 m_ptr->dealt_damage += dam;
696 if (m_ptr->dealt_damage > m_ptr->max_maxhp * 100)
697 m_ptr->dealt_damage = m_ptr->max_maxhp * 100;
699 if (current_world_ptr->wizard) {
700 msg_format(_("合計%d/%dのダメージを与えた。", "You do %d (out of %d) damage."), m_ptr->dealt_damage, m_ptr->maxhp);
705 GAME_TEXT m_name[MAX_NLEN];
707 if (r_info[m_ptr->r_idx].flags7 & RF7_TANUKI) {
708 /* You might have unmasked Tanuki first time */
709 r_ptr = &r_info[m_ptr->r_idx];
710 m_ptr->ap_r_idx = m_ptr->r_idx;
711 if (r_ptr->r_sights < MAX_SHORT)
715 if (m_ptr->mflag2 & MFLAG2_CHAMELEON) {
716 /* You might have unmasked Chameleon first time */
717 r_ptr = real_r_ptr(m_ptr);
718 if (r_ptr->r_sights < MAX_SHORT)
722 if (!(m_ptr->smart & SM_CLONED)) {
723 /* When the player kills a Unique, it stays dead */
724 if (r_ptr->flags1 & RF1_UNIQUE) {
727 /* Mega-Hack -- Banor & Lupart */
728 if ((m_ptr->r_idx == MON_BANOR) || (m_ptr->r_idx == MON_LUPART)) {
729 r_info[MON_BANORLUPART].max_num = 0;
730 r_info[MON_BANORLUPART].r_pkills++;
731 r_info[MON_BANORLUPART].r_akills++;
732 if (r_info[MON_BANORLUPART].r_tkills < MAX_SHORT)
733 r_info[MON_BANORLUPART].r_tkills++;
734 } else if (m_ptr->r_idx == MON_BANORLUPART) {
735 r_info[MON_BANOR].max_num = 0;
736 r_info[MON_BANOR].r_pkills++;
737 r_info[MON_BANOR].r_akills++;
738 if (r_info[MON_BANOR].r_tkills < MAX_SHORT)
739 r_info[MON_BANOR].r_tkills++;
740 r_info[MON_LUPART].max_num = 0;
741 r_info[MON_LUPART].r_pkills++;
742 r_info[MON_LUPART].r_akills++;
743 if (r_info[MON_LUPART].r_tkills < MAX_SHORT)
744 r_info[MON_LUPART].r_tkills++;
748 /* When the player kills a Nazgul, it stays dead */
749 else if (r_ptr->flags7 & RF7_NAZGUL)
753 /* Count all monsters killed */
754 if (r_ptr->r_akills < MAX_SHORT)
757 /* Recall even invisible uniques or winners */
758 if ((m_ptr->ml && !target_ptr->image) || (r_ptr->flags1 & RF1_UNIQUE)) {
759 /* Count kills this life */
760 if ((m_ptr->mflag2 & MFLAG2_KAGE) && (r_info[MON_KAGE].r_pkills < MAX_SHORT))
761 r_info[MON_KAGE].r_pkills++;
762 else if (r_ptr->r_pkills < MAX_SHORT)
765 /* Count kills in all lives */
766 if ((m_ptr->mflag2 & MFLAG2_KAGE) && (r_info[MON_KAGE].r_tkills < MAX_SHORT))
767 r_info[MON_KAGE].r_tkills++;
768 else if (r_ptr->r_tkills < MAX_SHORT)
771 /* Hack -- Auto-recall */
772 monster_race_track(target_ptr, m_ptr->ap_r_idx);
775 monster_desc(target_ptr, m_name, m_ptr, MD_TRUE_NAME);
777 /* Don't kill Amberites */
778 if ((r_ptr->flags3 & RF3_AMBERITE) && one_in_(2)) {
779 int curses = 1 + randint1(3);
780 bool stop_ty = FALSE;
783 msg_format(_("%^sは恐ろしい血の呪いをあなたにかけた!", "%^s puts a terrible blood curse on you!"), m_name);
784 curse_equipment(target_ptr, 100, 50);
787 stop_ty = activate_ty_curse(target_ptr, stop_ty, &count);
791 if (r_ptr->flags2 & RF2_CAN_SPEAK) {
793 if (!get_rnd_line(_("mondeath_j.txt", "mondeath.txt"), m_ptr->r_idx, line_got)) {
794 msg_format("%^s %s", m_name, line_got);
798 if (m_ptr->r_idx == MON_SERPENT) {
799 screen_dump = make_screen_dump(target_ptr, process_autopick_file_command);
804 if (!(d_info[target_ptr->dungeon_idx].flags1 & DF1_BEGINNER)) {
805 if (!target_ptr->current_floor_ptr->dun_level && !target_ptr->ambush_flag && !target_ptr->current_floor_ptr->inside_arena) {
806 chg_virtue(target_ptr, V_VALOUR, -1);
807 } else if (r_ptr->level > target_ptr->current_floor_ptr->dun_level) {
808 if (randint1(10) <= (r_ptr->level - target_ptr->current_floor_ptr->dun_level))
809 chg_virtue(target_ptr, V_VALOUR, 1);
811 if (r_ptr->level > 60) {
812 chg_virtue(target_ptr, V_VALOUR, 1);
814 if (r_ptr->level >= 2 * (target_ptr->lev + 1))
815 chg_virtue(target_ptr, V_VALOUR, 2);
818 if (r_ptr->flags1 & RF1_UNIQUE) {
819 if (r_ptr->flags3 & (RF3_EVIL | RF3_GOOD))
820 chg_virtue(target_ptr, V_HARMONY, 2);
822 if (r_ptr->flags3 & RF3_GOOD) {
823 chg_virtue(target_ptr, V_UNLIFE, 2);
824 chg_virtue(target_ptr, V_VITALITY, -2);
828 chg_virtue(target_ptr, V_INDIVIDUALISM, -1);
831 if (m_ptr->r_idx == MON_BEGGAR || m_ptr->r_idx == MON_LEPER) {
832 chg_virtue(target_ptr, V_COMPASSION, -1);
835 if ((r_ptr->flags3 & RF3_GOOD) && ((r_ptr->level) / 10 + (3 * target_ptr->current_floor_ptr->dun_level) >= randint1(100)))
836 chg_virtue(target_ptr, V_UNLIFE, 1);
838 if (r_ptr->d_char == 'A') {
839 if (r_ptr->flags1 & RF1_UNIQUE)
840 chg_virtue(target_ptr, V_FAITH, -2);
841 else if ((r_ptr->level) / 10 + (3 * target_ptr->current_floor_ptr->dun_level) >= randint1(100)) {
842 if (r_ptr->flags3 & RF3_GOOD)
843 chg_virtue(target_ptr, V_FAITH, -1);
845 chg_virtue(target_ptr, V_FAITH, 1);
847 } else if (r_ptr->flags3 & RF3_DEMON) {
848 if (r_ptr->flags1 & RF1_UNIQUE)
849 chg_virtue(target_ptr, V_FAITH, 2);
850 else if ((r_ptr->level) / 10 + (3 * target_ptr->current_floor_ptr->dun_level) >= randint1(100))
851 chg_virtue(target_ptr, V_FAITH, 1);
854 if ((r_ptr->flags3 & RF3_UNDEAD) && (r_ptr->flags1 & RF1_UNIQUE))
855 chg_virtue(target_ptr, V_VITALITY, 2);
857 if (r_ptr->r_deaths) {
858 if (r_ptr->flags1 & RF1_UNIQUE) {
859 chg_virtue(target_ptr, V_HONOUR, 10);
860 } else if ((r_ptr->level) / 10 + (2 * target_ptr->current_floor_ptr->dun_level) >= randint1(100)) {
861 chg_virtue(target_ptr, V_HONOUR, 1);
864 if ((r_ptr->flags2 & RF2_MULTIPLY) && (r_ptr->r_akills > 1000) && one_in_(10)) {
865 chg_virtue(target_ptr, V_VALOUR, -1);
868 for (i = 0; i < 4; i++) {
869 if (r_ptr->blow[i].d_dice != 0)
870 innocent = FALSE; /* Murderer! */
872 if ((r_ptr->blow[i].effect == RBE_EAT_ITEM) || (r_ptr->blow[i].effect == RBE_EAT_GOLD))
874 thief = TRUE; /* Thief! */
877 /* The new law says it is illegal to live in the dungeon */
878 if (r_ptr->level != 0)
882 if (r_ptr->flags1 & RF1_UNIQUE)
883 chg_virtue(target_ptr, V_JUSTICE, 3);
884 else if (1 + ((r_ptr->level) / 10 + (2 * target_ptr->current_floor_ptr->dun_level)) >= randint1(100))
885 chg_virtue(target_ptr, V_JUSTICE, 1);
886 } else if (innocent) {
887 chg_virtue(target_ptr, V_JUSTICE, -1);
890 if ((r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags3 & RF3_EVIL) && !(r_ptr->flags4 & ~(RF4_NOMAGIC_MASK))
891 && !(r_ptr->a_ability_flags1 & ~(RF5_NOMAGIC_MASK)) && !(r_ptr->a_ability_flags2 & ~(RF6_NOMAGIC_MASK))) {
893 chg_virtue(target_ptr, V_NATURE, -1);
896 if ((r_ptr->flags1 & RF1_UNIQUE) && record_destroy_uniq) {
898 sprintf(note_buf, "%s%s", r_name + r_ptr->name, (m_ptr->smart & SM_CLONED) ? _("(クローン)", "(Clone)") : "");
899 exe_write_diary(target_ptr, DIARY_UNIQUE, 0, note_buf);
905 /* Death by Missile/Spell attack */
907 msg_format("%^s%s", m_name, note);
910 /* Death by physical attack -- invisible monster */
911 else if (!m_ptr->ml) {
913 if (is_echizen(target_ptr))
914 msg_format("せっかくだから%sを殺した。", m_name);
916 msg_format("%sを殺した。", m_name);
918 msg_format("You have killed %s.", m_name);
923 /* Death by Physical attack -- non-living monster */
924 else if (!monster_living(m_ptr->r_idx)) {
925 bool explode = FALSE;
927 for (i = 0; i < 4; i++) {
928 if (r_ptr->blow[i].method == RBM_EXPLODE)
932 /* Special note at death */
934 msg_format(_("%sは爆発して粉々になった。", "%^s explodes into tiny shreds."), m_name);
937 if (is_echizen(target_ptr))
938 msg_format("せっかくだから%sを倒した。", m_name);
940 msg_format("%sを倒した。", m_name);
942 msg_format("You have destroyed %s.", m_name);
947 /* Death by Physical attack -- living monster */
950 if (is_echizen(target_ptr))
951 msg_format("せっかくだから%sを葬り去った。", m_name);
953 msg_format("%sを葬り去った。", m_name);
955 msg_format("You have slain %s.", m_name);
958 if ((r_ptr->flags1 & RF1_UNIQUE) && !(m_ptr->smart & SM_CLONED) && !vanilla_town) {
959 for (i = 0; i < MAX_BOUNTY; i++) {
960 if ((current_world_ptr->bounty_r_idx[i] == m_ptr->r_idx) && !(m_ptr->mflag2 & MFLAG2_CHAMELEON)) {
961 msg_format(_("%sの首には賞金がかかっている。", "There is a price on %s's head."), m_name);
967 /* Generate treasure */
968 monster_death(target_ptr, m_idx, TRUE);
970 /* Mega hack : replace IKETA to BIKETAL */
971 if ((m_ptr->r_idx == MON_IKETA) && !(target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out)) {
972 POSITION dummy_y = m_ptr->fy;
973 POSITION dummy_x = m_ptr->fx;
976 mode |= PM_FORCE_PET;
977 delete_monster_idx(target_ptr, m_idx);
978 if (summon_named_creature(target_ptr, 0, dummy_y, dummy_x, MON_BIKETAL, mode)) {
979 msg_print(_("「ハァッハッハッハ!!私がバイケタルだ!!」", "Uwa-hahaha! *I* am Biketal!"));
982 delete_monster_idx(target_ptr, m_idx);
985 get_exp_from_mon(target_ptr, (long)exp_mon.max_maxhp * 2, &exp_mon);
990 /* Monster is dead */
994 /* Mega-Hack -- Pain cancels fear */
995 if (monster_fear_remaining(m_ptr) && (dam > 0)) {
997 if (set_monster_monfear(target_ptr, m_idx, monster_fear_remaining(m_ptr) - randint1(dam))) {
1003 /* Sometimes a monster gets scared by damage */
1004 if (!monster_fear_remaining(m_ptr) && !(r_ptr->flags3 & (RF3_NO_FEAR))) {
1005 /* Percentage of fully healthy */
1006 int percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
1009 * Run (sometimes) if at 10% or less of max hit points,
1010 * or (usually) when hit for half its current hit points
1012 if ((randint1(10) >= percentage) || ((dam >= m_ptr->hp) && (randint0(100) < 80))) {
1013 /* Hack -- note fear */
1016 /* Hack -- Add some timed fear */
1017 (void)set_monster_monfear(target_ptr, m_idx, (randint1(10) + (((dam >= m_ptr->hp) && (percentage > 7)) ? 20 : ((11 - percentage) * 5))));
1025 bool monster_is_valid(monster_type *m_ptr) { return (m_ptr->r_idx != 0); }
1027 TIME_EFFECT monster_csleep_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_CSLEEP]; }
1029 TIME_EFFECT monster_fast_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_FAST]; }
1031 TIME_EFFECT monster_slow_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_SLOW]; }
1033 TIME_EFFECT monster_stunned_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_STUNNED]; }
1035 TIME_EFFECT monster_confused_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_CONFUSED]; }
1037 TIME_EFFECT monster_fear_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_MONFEAR]; }
1039 TIME_EFFECT monster_invulner_remaining(monster_type *m_ptr) { return m_ptr->mtimed[MTIMED_INVULNER]; }