OSDN Git Service

[Refactor] #37353 コメント整理 / Refactor comments.
[hengband/hengband.git] / src / monster-status.c
1 #include "angband.h"
2
3
4 /*!
5 * @brief モンスターの時限ステータスを取得する
6 * @return m_idx モンスターの参照ID
7 * @return mproc_type モンスターの時限ステータスID
8 * @return 残りターン値
9 */
10 int get_mproc_idx(MONSTER_IDX m_idx, int mproc_type)
11 {
12         s16b *cur_mproc_list = mproc_list[mproc_type];
13         int i;
14
15         for (i = mproc_max[mproc_type] - 1; i >= 0; i--)
16         {
17                 if (cur_mproc_list[i] == m_idx) return i;
18         }
19
20         return -1;
21 }
22
23 /*!
24 * @brief モンスターの時限ステータスリストを追加する
25 * @return m_idx モンスターの参照ID
26 * @return mproc_type 追加したいモンスターの時限ステータスID
27 * @return なし
28 */
29 static void mproc_add(MONSTER_IDX m_idx, int mproc_type)
30 {
31         if (mproc_max[mproc_type] < max_m_idx) mproc_list[mproc_type][mproc_max[mproc_type]++] = (s16b)m_idx;
32 }
33
34
35 /*!
36 * @brief モンスターの時限ステータスリストを削除
37 * @return m_idx モンスターの参照ID
38 * @return mproc_type 削除したいモンスターの時限ステータスID
39 * @return なし
40 */
41 static void mproc_remove(MONSTER_IDX m_idx, int mproc_type)
42 {
43         int mproc_idx = get_mproc_idx(m_idx, mproc_type);
44         if (mproc_idx >= 0) mproc_list[mproc_type][mproc_idx] = mproc_list[mproc_type][--mproc_max[mproc_type]];
45 }
46
47
48 /*!
49 * @brief モンスターの時限ステータスリストを初期化する / Initialize monster process
50 * @return なし
51 */
52 void mproc_init(void)
53 {
54         monster_type *m_ptr;
55         MONSTER_IDX i;
56         int cmi;
57
58         /* Reset "mproc_max[]" */
59         for (cmi = 0; cmi < MAX_MTIMED; cmi++) mproc_max[cmi] = 0;
60
61         /* Process the monsters (backwards) */
62         for (i = m_max - 1; i >= 1; i--)
63         {
64                 /* Access the monster */
65                 m_ptr = &m_list[i];
66
67                 /* Ignore "dead" monsters */
68                 if (!m_ptr->r_idx) continue;
69
70                 for (cmi = 0; cmi < MAX_MTIMED; cmi++)
71                 {
72                         if (m_ptr->mtimed[cmi]) mproc_add(i, cmi);
73                 }
74         }
75 }
76
77
78 /*!
79 * @brief モンスターの睡眠状態値をセットする /
80 * Set "m_ptr->mtimed[MTIMED_CSLEEP]", notice observable changes
81 * @param m_idx モンスター参照ID
82 * @param v セットする値
83 * @return 別途更新処理が必要な場合TRUEを返す
84 */
85 bool set_monster_csleep(MONSTER_IDX m_idx, int v)
86 {
87         monster_type *m_ptr = &m_list[m_idx];
88         bool notice = FALSE;
89
90         /* Hack -- Force good values */
91         v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
92
93         /* Open */
94         if (v)
95         {
96                 if (!MON_CSLEEP(m_ptr))
97                 {
98                         mproc_add(m_idx, MTIMED_CSLEEP);
99                         notice = TRUE;
100                 }
101         }
102
103         /* Shut */
104         else
105         {
106                 if (MON_CSLEEP(m_ptr))
107                 {
108                         mproc_remove(m_idx, MTIMED_CSLEEP);
109                         notice = TRUE;
110                 }
111         }
112
113         /* Use the value */
114         m_ptr->mtimed[MTIMED_CSLEEP] = (s16b)v;
115
116         if (!notice) return FALSE;
117
118         if (m_ptr->ml)
119         {
120                 /* Update health bar as needed */
121                 if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
122                 if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
123         }
124
125         if (r_info[m_ptr->r_idx].flags7 & RF7_HAS_LD_MASK) p_ptr->update |= (PU_MON_LITE);
126
127         return TRUE;
128 }
129
130
131 /*!
132 * @brief モンスターの加速状態値をセット /
133 * Set "m_ptr->mtimed[MTIMED_FAST]", notice observable changes
134 * @param m_idx モンスター参照ID
135 * @param v セットする値
136 * @return 別途更新処理が必要な場合TRUEを返す
137 */
138 bool set_monster_fast(MONSTER_IDX m_idx, int v)
139 {
140         monster_type *m_ptr = &m_list[m_idx];
141         bool notice = FALSE;
142
143         /* Hack -- Force good values */
144         v = (v > 200) ? 200 : (v < 0) ? 0 : v;
145
146         /* Open */
147         if (v)
148         {
149                 if (!MON_FAST(m_ptr))
150                 {
151                         mproc_add(m_idx, MTIMED_FAST);
152                         notice = TRUE;
153                 }
154         }
155
156         /* Shut */
157         else
158         {
159                 if (MON_FAST(m_ptr))
160                 {
161                         mproc_remove(m_idx, MTIMED_FAST);
162                         notice = TRUE;
163                 }
164         }
165
166         /* Use the value */
167         m_ptr->mtimed[MTIMED_FAST] = (s16b)v;
168
169         if (!notice) return FALSE;
170
171         if ((p_ptr->riding == m_idx) && !p_ptr->leaving) p_ptr->update |= (PU_BONUS);
172
173         return TRUE;
174 }
175
176
177 /*
178 * Set "m_ptr->mtimed[MTIMED_SLOW]", notice observable changes
179 */
180 bool set_monster_slow(MONSTER_IDX m_idx, int v)
181 {
182         monster_type *m_ptr = &m_list[m_idx];
183         bool notice = FALSE;
184
185         /* Hack -- Force good values */
186         v = (v > 200) ? 200 : (v < 0) ? 0 : v;
187
188         /* Open */
189         if (v)
190         {
191                 if (!MON_SLOW(m_ptr))
192                 {
193                         mproc_add(m_idx, MTIMED_SLOW);
194                         notice = TRUE;
195                 }
196         }
197
198         /* Shut */
199         else
200         {
201                 if (MON_SLOW(m_ptr))
202                 {
203                         mproc_remove(m_idx, MTIMED_SLOW);
204                         notice = TRUE;
205                 }
206         }
207
208         /* Use the value */
209         m_ptr->mtimed[MTIMED_SLOW] = (s16b)v;
210
211         if (!notice) return FALSE;
212
213         if ((p_ptr->riding == m_idx) && !p_ptr->leaving) p_ptr->update |= (PU_BONUS);
214
215         return TRUE;
216 }
217
218
219 /*!
220 * @brief モンスターの朦朧状態値をセット /
221 * Set "m_ptr->mtimed[MTIMED_STUNNED]", notice observable changes
222 * @param m_idx モンスター参照ID
223 * @param v セットする値
224 * @return 別途更新処理が必要な場合TRUEを返す
225 */
226 bool set_monster_stunned(MONSTER_IDX m_idx, int v)
227 {
228         monster_type *m_ptr = &m_list[m_idx];
229         bool notice = FALSE;
230
231         /* Hack -- Force good values */
232         v = (v > 200) ? 200 : (v < 0) ? 0 : v;
233
234         /* Open */
235         if (v)
236         {
237                 if (!MON_STUNNED(m_ptr))
238                 {
239                         mproc_add(m_idx, MTIMED_STUNNED);
240                         notice = TRUE;
241                 }
242         }
243
244         /* Shut */
245         else
246         {
247                 if (MON_STUNNED(m_ptr))
248                 {
249                         mproc_remove(m_idx, MTIMED_STUNNED);
250                         notice = TRUE;
251                 }
252         }
253
254         /* Use the value */
255         m_ptr->mtimed[MTIMED_STUNNED] = (s16b)v;
256
257         return notice;
258 }
259
260
261 /*!
262 * @brief モンスターの混乱状態値をセット /
263 * Set "m_ptr->mtimed[MTIMED_CONFUSED]", notice observable changes
264 * @param m_idx モンスター参照ID
265 * @param v セットする値
266 * @return 別途更新処理が必要な場合TRUEを返す
267 */
268 bool set_monster_confused(MONSTER_IDX m_idx, int v)
269 {
270         monster_type *m_ptr = &m_list[m_idx];
271         bool notice = FALSE;
272
273         /* Hack -- Force good values */
274         v = (v > 200) ? 200 : (v < 0) ? 0 : v;
275
276         /* Open */
277         if (v)
278         {
279                 if (!MON_CONFUSED(m_ptr))
280                 {
281                         mproc_add(m_idx, MTIMED_CONFUSED);
282                         notice = TRUE;
283                 }
284         }
285
286         /* Shut */
287         else
288         {
289                 if (MON_CONFUSED(m_ptr))
290                 {
291                         mproc_remove(m_idx, MTIMED_CONFUSED);
292                         notice = TRUE;
293                 }
294         }
295
296         /* Use the value */
297         m_ptr->mtimed[MTIMED_CONFUSED] = (s16b)v;
298
299         return notice;
300 }
301
302
303 /*!
304 * @brief モンスターの恐慌状態値をセット /
305 * Set "m_ptr->mtimed[MTIMED_MONFEAR]", notice observable changes
306 * @param m_idx モンスター参照ID
307 * @param v セットする値
308 * @return 別途更新処理が必要な場合TRUEを返す
309 */
310 bool set_monster_monfear(MONSTER_IDX m_idx, int v)
311 {
312         monster_type *m_ptr = &m_list[m_idx];
313         bool notice = FALSE;
314
315         /* Hack -- Force good values */
316         v = (v > 200) ? 200 : (v < 0) ? 0 : v;
317
318         /* Open */
319         if (v)
320         {
321                 if (!MON_MONFEAR(m_ptr))
322                 {
323                         mproc_add(m_idx, MTIMED_MONFEAR);
324                         notice = TRUE;
325                 }
326         }
327
328         /* Shut */
329         else
330         {
331                 if (MON_MONFEAR(m_ptr))
332                 {
333                         mproc_remove(m_idx, MTIMED_MONFEAR);
334                         notice = TRUE;
335                 }
336         }
337
338         /* Use the value */
339         m_ptr->mtimed[MTIMED_MONFEAR] = (s16b)v;
340
341         if (!notice) return FALSE;
342
343         if (m_ptr->ml)
344         {
345                 /* Update health bar as needed */
346                 if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
347                 if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
348         }
349
350         return TRUE;
351 }
352
353
354 /*!
355 * @brief モンスターの無敵状態値をセット /
356 * Set "m_ptr->mtimed[MTIMED_INVULNER]", notice observable changes
357 * @param m_idx モンスター参照ID
358 * @param v セットする値
359 * @param energy_need TRUEならば無敵解除時に行動ターン消費を行う
360 * @return 別途更新処理が必要な場合TRUEを返す
361 */
362 bool set_monster_invulner(MONSTER_IDX m_idx, int v, bool energy_need)
363 {
364         monster_type *m_ptr = &m_list[m_idx];
365         bool notice = FALSE;
366
367         /* Hack -- Force good values */
368         v = (v > 200) ? 200 : (v < 0) ? 0 : v;
369
370         /* Open */
371         if (v)
372         {
373                 if (!MON_INVULNER(m_ptr))
374                 {
375                         mproc_add(m_idx, MTIMED_INVULNER);
376                         notice = TRUE;
377                 }
378         }
379
380         /* Shut */
381         else
382         {
383                 if (MON_INVULNER(m_ptr))
384                 {
385                         mproc_remove(m_idx, MTIMED_INVULNER);
386                         if (energy_need && !p_ptr->wild_mode) m_ptr->energy_need += ENERGY_NEED();
387                         notice = TRUE;
388                 }
389         }
390
391         /* Use the value */
392         m_ptr->mtimed[MTIMED_INVULNER] = (s16b)v;
393
394         if (!notice) return FALSE;
395
396         if (m_ptr->ml)
397         {
398                 /* Update health bar as needed */
399                 if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
400                 if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
401         }
402
403         return TRUE;
404 }
405
406
407 static u32b csleep_noise;
408
409 /*!
410 * @brief モンスターの各種状態値を時間経過により更新するサブルーチン
411 * @param m_idx モンスター参照ID
412 * @param mtimed_idx 更新するモンスターの時限ステータスID
413 * @return なし
414 */
415 static void process_monsters_mtimed_aux(MONSTER_IDX m_idx, int mtimed_idx)
416 {
417         monster_type *m_ptr = &m_list[m_idx];
418
419         switch (mtimed_idx)
420         {
421         case MTIMED_CSLEEP:
422         {
423                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
424
425                 /* Assume does not wake up */
426                 bool test = FALSE;
427
428                 /* Hack -- Require proximity */
429                 if (m_ptr->cdis < AAF_LIMIT)
430                 {
431                         /* Handle "sensing radius" */
432                         if (m_ptr->cdis <= (is_pet(m_ptr) ? ((r_ptr->aaf > MAX_SIGHT) ? MAX_SIGHT : r_ptr->aaf) : r_ptr->aaf))
433                         {
434                                 /* We may wake up */
435                                 test = TRUE;
436                         }
437
438                         /* Handle "sight" and "aggravation" */
439                         else if ((m_ptr->cdis <= MAX_SIGHT) && (player_has_los_bold(m_ptr->fy, m_ptr->fx)))
440                         {
441                                 /* We may wake up */
442                                 test = TRUE;
443                         }
444                 }
445
446                 if (test)
447                 {
448                         u32b notice = randint0(1024);
449
450                         /* Nightmare monsters are more alert */
451                         if (ironman_nightmare) notice /= 2;
452
453                         /* Hack -- See if monster "notices" player */
454                         if ((notice * notice * notice) <= csleep_noise)
455                         {
456                                 /* Hack -- amount of "waking" */
457                                 /* Wake up faster near the player */
458                                 int d = (m_ptr->cdis < AAF_LIMIT / 2) ? (AAF_LIMIT / m_ptr->cdis) : 1;
459
460                                 /* Hack -- amount of "waking" is affected by speed of player */
461                                 d = (d * SPEED_TO_ENERGY(p_ptr->pspeed)) / 10;
462                                 if (d < 0) d = 1;
463
464                                 /* Monster wakes up "a little bit" */
465
466                                 /* Still asleep */
467                                 if (!set_monster_csleep(m_idx, MON_CSLEEP(m_ptr) - d))
468                                 {
469                                         /* Notice the "not waking up" */
470                                         if (is_original_ap_and_seen(m_ptr))
471                                         {
472                                                 /* Hack -- Count the ignores */
473                                                 if (r_ptr->r_ignore < MAX_UCHAR) r_ptr->r_ignore++;
474                                         }
475                                 }
476
477                                 /* Just woke up */
478                                 else
479                                 {
480                                         /* Notice the "waking up" */
481                                         if (m_ptr->ml)
482                                         {
483                                                 char m_name[80];
484                                                 monster_desc(m_name, m_ptr, 0);
485                                                 msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
486                                         }
487
488                                         if (is_original_ap_and_seen(m_ptr))
489                                         {
490                                                 /* Hack -- Count the wakings */
491                                                 if (r_ptr->r_wake < MAX_UCHAR) r_ptr->r_wake++;
492                                         }
493                                 }
494                         }
495                 }
496                 break;
497         }
498
499         case MTIMED_FAST:
500                 /* Reduce by one, note if expires */
501                 if (set_monster_fast(m_idx, MON_FAST(m_ptr) - 1))
502                 {
503                         if (is_seen(m_ptr))
504                         {
505                                 char m_name[80];
506                                 monster_desc(m_name, m_ptr, 0);
507                                 msg_format(_("%^sはもう加速されていない。", "%^s is no longer fast."), m_name);
508                         }
509                 }
510                 break;
511
512         case MTIMED_SLOW:
513                 /* Reduce by one, note if expires */
514                 if (set_monster_slow(m_idx, MON_SLOW(m_ptr) - 1))
515                 {
516                         if (is_seen(m_ptr))
517                         {
518                                 char m_name[80];
519                                 monster_desc(m_name, m_ptr, 0);
520                                 msg_format(_("%^sはもう減速されていない。", "%^s is no longer slow."), m_name);
521                         }
522                 }
523                 break;
524
525         case MTIMED_STUNNED:
526         {
527                 int rlev = r_info[m_ptr->r_idx].level;
528
529                 /* Recover from stun */
530                 if (set_monster_stunned(m_idx, (randint0(10000) <= rlev * rlev) ? 0 : (MON_STUNNED(m_ptr) - 1)))
531                 {
532                         /* Message if visible */
533                         if (is_seen(m_ptr))
534                         {
535                                 char m_name[80];
536                                 monster_desc(m_name, m_ptr, 0);
537                                 msg_format(_("%^sは朦朧状態から立ち直った。", "%^s is no longer stunned."), m_name);
538                         }
539                 }
540                 break;
541         }
542
543         case MTIMED_CONFUSED:
544                 /* Reduce the confusion */
545                 if (set_monster_confused(m_idx, MON_CONFUSED(m_ptr) - randint1(r_info[m_ptr->r_idx].level / 20 + 1)))
546                 {
547                         /* Message if visible */
548                         if (is_seen(m_ptr))
549                         {
550                                 char m_name[80];
551                                 monster_desc(m_name, m_ptr, 0);
552                                 msg_format(_("%^sは混乱から立ち直った。", "%^s is no longer confused."), m_name);
553                         }
554                 }
555                 break;
556
557         case MTIMED_MONFEAR:
558                 /* Reduce the fear */
559                 if (set_monster_monfear(m_idx, MON_MONFEAR(m_ptr) - randint1(r_info[m_ptr->r_idx].level / 20 + 1)))
560                 {
561                         /* Visual note */
562                         if (is_seen(m_ptr))
563                         {
564                                 char m_name[80];
565 #ifndef JP
566                                 char m_poss[80];
567
568                                 /* Acquire the monster possessive */
569                                 monster_desc(m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
570 #endif
571                                 monster_desc(m_name, m_ptr, 0);
572 #ifdef JP
573                                 msg_format("%^sは勇気を取り戻した。", m_name);
574 #else
575                                 msg_format("%^s recovers %s courage.", m_name, m_poss);
576 #endif
577                         }
578                 }
579                 break;
580
581         case MTIMED_INVULNER:
582                 /* Reduce by one, note if expires */
583                 if (set_monster_invulner(m_idx, MON_INVULNER(m_ptr) - 1, TRUE))
584                 {
585                         if (is_seen(m_ptr))
586                         {
587                                 char m_name[80];
588                                 monster_desc(m_name, m_ptr, 0);
589                                 msg_format(_("%^sはもう無敵でない。", "%^s is no longer invulnerable."), m_name);
590                         }
591                 }
592                 break;
593         }
594 }
595
596
597 /*!
598 * @brief 全モンスターの各種状態値を時間経過により更新するメインルーチン
599 * @param mtimed_idx 更新するモンスターの時限ステータスID
600 * @return なし
601 * @details
602 * Process the counters of monsters (once per 10 game turns)\n
603 * These functions are to process monsters' counters same as player's.
604 */
605 void process_monsters_mtimed(int mtimed_idx)
606 {
607         int  i;
608         s16b *cur_mproc_list = mproc_list[mtimed_idx];
609
610         /* Hack -- calculate the "player noise" */
611         if (mtimed_idx == MTIMED_CSLEEP) csleep_noise = (1L << (30 - p_ptr->skill_stl));
612
613         /* Process the monsters (backwards) */
614         for (i = mproc_max[mtimed_idx] - 1; i >= 0; i--)
615         {
616                 /* Access the monster */
617                 process_monsters_mtimed_aux(cur_mproc_list[i], mtimed_idx);
618         }
619 }
620
621 /*!
622 * @brief モンスターへの魔力消去処理
623 * @param m_idx 魔力消去を受けるモンスターの参照ID
624 * @return なし
625 */
626 void dispel_monster_status(MONSTER_IDX m_idx)
627 {
628         monster_type *m_ptr = &m_list[m_idx];
629         char         m_name[80];
630
631         monster_desc(m_name, m_ptr, 0);
632         if (set_monster_invulner(m_idx, 0, TRUE))
633         {
634                 if (m_ptr->ml) msg_format(_("%sはもう無敵ではない。", "%^s is no longer invulnerable."), m_name);
635         }
636         if (set_monster_fast(m_idx, 0))
637         {
638                 if (m_ptr->ml) msg_format(_("%sはもう加速されていない。", "%^s is no longer fast."), m_name);
639         }
640         if (set_monster_slow(m_idx, 0))
641         {
642                 if (m_ptr->ml) msg_format(_("%sはもう減速されていない。", "%^s is no longer slow."), m_name);
643         }
644 }
645
646 /*!
647 * @brief モンスターの時間停止処理
648 * @param num 時間停止を行った敵が行動できる回数
649 * @param who 時間停止処理の主体ID
650 * @param vs_player TRUEならば時間停止開始処理を行う
651 * @return 時間停止が行われている状態ならばTRUEを返す
652 */
653 bool process_the_world(int num, MONSTER_IDX who, bool vs_player)
654 {
655         monster_type *m_ptr = &m_list[hack_m_idx];  /* the world monster */
656
657         if (world_monster) return (FALSE);
658
659         if (vs_player)
660         {
661                 char m_name[80];
662                 monster_desc(m_name, m_ptr, 0);
663
664                 if (who == 1)
665                         msg_format(_("「『ザ・ワールド』!時は止まった!」", "%s yells 'The World! Time has stopped!'"), m_name);
666                 else if (who == 3)
667                         msg_format(_("「時よ!」", "%s yells 'Time!'"), m_name);
668                 else msg_print("hek!");
669
670                 msg_print(NULL);
671         }
672
673         /* This monster cast spells */
674         world_monster = hack_m_idx;
675
676         if (vs_player) do_cmd_redraw();
677
678         while (num--)
679         {
680                 if (!m_ptr->r_idx) break;
681                 process_monster(world_monster);
682
683                 reset_target(m_ptr);
684
685                 if (p_ptr->notice) notice_stuff();
686                 if (p_ptr->update) update_stuff();
687                 if (p_ptr->redraw) redraw_stuff();
688                 if (p_ptr->window) window_stuff();
689
690                 if (vs_player) Term_xtra(TERM_XTRA_DELAY, 500);
691         }
692
693         p_ptr->redraw |= (PR_MAP);
694
695         /* Update monsters */
696         p_ptr->update |= (PU_MONSTERS);
697
698         p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
699
700         world_monster = 0;
701         if (vs_player || (player_has_los_bold(m_ptr->fy, m_ptr->fx) && projectable(p_ptr->y, p_ptr->x, m_ptr->fy, m_ptr->fx)))
702         {
703                 msg_print(_("「時は動きだす…」", "You feel time flowing around you once more."));
704                 msg_print(NULL);
705         }
706
707         handle_stuff();
708
709         return (TRUE);
710 }
711
712 /*!
713 * @brief モンスターの経験値取得処理
714 * @param m_idx 経験値を得るモンスターの参照ID
715 * @param s_idx 撃破されたモンスター種族の参照ID
716 * @return なし
717 */
718 void monster_gain_exp(MONSTER_IDX m_idx, IDX s_idx)
719 {
720         monster_type *m_ptr;
721         monster_race *r_ptr;
722         monster_race *s_ptr;
723         int new_exp;
724
725         /* Paranoia */
726         if (m_idx <= 0 || s_idx <= 0) return;
727
728         m_ptr = &m_list[m_idx];
729
730         /* Paranoia -- Skip dead monsters */
731         if (!m_ptr->r_idx) return;
732
733         r_ptr = &r_info[m_ptr->r_idx];
734         s_ptr = &r_info[s_idx];
735
736         if (p_ptr->inside_battle) return;
737
738         if (!r_ptr->next_exp) return;
739
740         new_exp = s_ptr->mexp * s_ptr->level / (r_ptr->level + 2);
741         if (m_idx == p_ptr->riding) new_exp = (new_exp + 1) / 2;
742         if (!dun_level) new_exp /= 5;
743         m_ptr->exp += new_exp;
744         if (m_ptr->mflag2 & MFLAG2_CHAMELEON) return;
745
746         if (m_ptr->exp >= r_ptr->next_exp)
747         {
748                 char m_name[80];
749                 int old_hp = m_ptr->hp;
750                 int old_maxhp = m_ptr->max_maxhp;
751                 int old_r_idx = m_ptr->r_idx;
752                 byte old_sub_align = m_ptr->sub_align;
753
754                 /* Hack -- Reduce the racial counter of previous monster */
755                 real_r_ptr(m_ptr)->cur_num--;
756
757                 monster_desc(m_name, m_ptr, 0);
758                 m_ptr->r_idx = r_ptr->next_r_idx;
759
760                 /* Count the monsters on the level */
761                 real_r_ptr(m_ptr)->cur_num++;
762
763                 m_ptr->ap_r_idx = m_ptr->r_idx;
764                 r_ptr = &r_info[m_ptr->r_idx];
765
766                 if (r_ptr->flags1 & RF1_FORCE_MAXHP)
767                 {
768                         m_ptr->max_maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
769                 }
770                 else
771                 {
772                         m_ptr->max_maxhp = damroll(r_ptr->hdice, r_ptr->hside);
773                 }
774                 if (ironman_nightmare)
775                 {
776                         HIT_POINT hp = m_ptr->max_maxhp * 2L;
777                         m_ptr->max_maxhp = MIN(30000, hp);
778                 }
779                 m_ptr->maxhp = m_ptr->max_maxhp;
780                 m_ptr->hp = old_hp * m_ptr->maxhp / old_maxhp;
781
782                 /* dealt damage is 0 at initial*/
783                 m_ptr->dealt_damage = 0;
784
785                 /* Extract the monster base speed */
786                 m_ptr->mspeed = get_mspeed(r_ptr);
787
788                 /* Sub-alignment of a monster */
789                 if (!is_pet(m_ptr) && !(r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)))
790                         m_ptr->sub_align = old_sub_align;
791                 else
792                 {
793                         m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
794                         if (r_ptr->flags3 & RF3_EVIL) m_ptr->sub_align |= SUB_ALIGN_EVIL;
795                         if (r_ptr->flags3 & RF3_GOOD) m_ptr->sub_align |= SUB_ALIGN_GOOD;
796                 }
797
798                 m_ptr->exp = 0;
799
800                 if (is_pet(m_ptr) || m_ptr->ml)
801                 {
802                         if (!ignore_unview || player_can_see_bold(m_ptr->fy, m_ptr->fx))
803                         {
804                                 if (p_ptr->image)
805                                 {
806                                         monster_race *hallu_race;
807
808                                         do
809                                         {
810                                                 hallu_race = &r_info[randint1(max_r_idx - 1)];
811                                         } while (!hallu_race->name || (hallu_race->flags1 & RF1_UNIQUE));
812                                         msg_format(_("%sは%sに進化した。", "%^s evolved into %s."), m_name, r_name + hallu_race->name);
813                                 }
814                                 else
815                                 {
816                                         msg_format(_("%sは%sに進化した。", "%^s evolved into %s."), m_name, r_name + r_ptr->name);
817                                 }
818                         }
819
820                         if (!p_ptr->image) r_info[old_r_idx].r_xtra1 |= MR1_SINKA;
821
822                         /* Now you feel very close to this pet. */
823                         m_ptr->parent_m_idx = 0;
824                 }
825                 update_monster(m_idx, FALSE);
826                 lite_spot(m_ptr->fy, m_ptr->fx);
827         }
828         if (m_idx == p_ptr->riding) p_ptr->update |= PU_BONUS;
829 }