OSDN Git Service

Merge remote-tracking branch 'remotes/origin/feature/Fix-Sanity-Blast-by-AutoSave...
[hengband/hengband.git] / src / monster / monster-list.c
1 /*!
2  * @brief モンスター処理 / misc code for monsters
3  * @date 2014/07/08
4  * @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6  * This software may be copied and distributed for educational, research,
7  * and not for profit purposes provided that this copyright and statement
8  * are included in all such copies.  Other copyrights may also apply.
9  * 2014 Deskull rearranged comment for Doxygen.
10  */
11
12 #include "monster/monster-list.h"
13 #include "core/player-update-types.h"
14 #include "core/speed-table.h"
15 #include "dungeon/dungeon-flag-types.h"
16 #include "dungeon/dungeon.h"
17 #include "floor/cave.h"
18 #include "floor/floor-object.h"
19 #include "floor/wild.h"
20 #include "game-option/birth-options.h"
21 #include "game-option/cheat-options.h"
22 #include "grid/grid.h"
23 #include "monster-floor/monster-summon.h"
24 #include "monster-race/monster-race.h"
25 #include "monster-race/race-flags1.h"
26 #include "monster-race/race-flags2.h"
27 #include "monster-race/race-flags3.h"
28 #include "monster-race/race-flags7.h"
29 #include "monster-race/race-indice-types.h"
30 #include "monster/monster-describer.h"
31 #include "monster/monster-info.h"
32 #include "monster/monster-update.h"
33 #include "monster/monster-util.h"
34 #include "object/object-generator.h"
35 #include "pet/pet-fall-off.h"
36 #include "system/alloc-entries.h"
37 #include "system/floor-type-definition.h"
38 #include "view/display-messages.h"
39 #include "world/world.h"
40
41 #define HORDE_NOGOOD 0x01 /*!< (未実装フラグ)HORDE生成でGOODなモンスターの生成を禁止する? */
42 #define HORDE_NOEVIL 0x02 /*!< (未実装フラグ)HORDE生成でEVILなモンスターの生成を禁止する? */
43
44 /*!
45  * @brief モンスター配列の空きを探す / Acquires and returns the index of a "free" monster.
46  * @return 利用可能なモンスター配列の添字
47  * @details
48  * This routine should almost never fail, but it *can* happen.
49  */
50 MONSTER_IDX m_pop(floor_type *floor_ptr)
51 {
52     /* Normal allocation */
53     if (floor_ptr->m_max < current_world_ptr->max_m_idx) {
54         MONSTER_IDX i = floor_ptr->m_max;
55         floor_ptr->m_max++;
56         floor_ptr->m_cnt++;
57         return i;
58     }
59
60     /* Recycle dead monsters */
61     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
62         monster_type *m_ptr;
63         m_ptr = &floor_ptr->m_list[i];
64         if (m_ptr->r_idx)
65             continue;
66         floor_ptr->m_cnt++;
67         return i;
68     }
69
70     if (current_world_ptr->character_dungeon)
71         msg_print(_("モンスターが多すぎる!", "Too many monsters!"));
72     return 0;
73 }
74
75 /*!
76  * @brief 生成モンスター種族を1種生成テーブルから選択する
77  * @param player_ptr プレーヤーへの参照ポインタ
78  * @param min_level 最小生成階
79  * @param max_level 最大生成階
80  * @return 選択されたモンスター生成種族
81  */
82 MONRACE_IDX get_mon_num(player_type *player_ptr, DEPTH min_level, DEPTH max_level, BIT_FLAGS option)
83 {
84     int i, j, p;
85     int r_idx;
86     long value, total;
87     int mon_num = 0;
88     monster_race *r_ptr;
89     alloc_entry *table = alloc_race_table;
90
91     int pls_kakuritu, pls_max_level, over_days;
92     int delay = mysqrt(max_level * 10000L) + (max_level * 5);
93
94     /* town max_level : same delay as 10F, no nasty mons till day18 */
95     if (!max_level)
96         delay = 360;
97
98     if (max_level > MAX_DEPTH - 1)
99         max_level = MAX_DEPTH - 1;
100
101     /* +1 per day after the base date */
102     /* base dates : day5(1F), day18(10F,0F), day34(30F), day53(60F), day69(90F) */
103     over_days = MAX(0, current_world_ptr->dungeon_turn / (TURNS_PER_TICK * 10000L) - delay / 20);
104
105     /* starts from 1/25, reaches 1/3 after 44days from a max_level dependent base date */
106     pls_kakuritu = MAX(NASTY_MON_MAX, NASTY_MON_BASE - over_days / 2);
107     /* starts from 0, reaches +25lv after 75days from a max_level dependent base date */
108     pls_max_level = MIN(NASTY_MON_PLUS_MAX, over_days / 3);
109
110     if (d_info[player_ptr->dungeon_idx].flags1 & DF1_MAZE) {
111         pls_kakuritu = MIN(pls_kakuritu / 2, pls_kakuritu - 10);
112         if (pls_kakuritu < 2)
113             pls_kakuritu = 2;
114         pls_max_level += 2;
115         max_level += 3;
116     }
117
118     /* Boost the max_level */
119     if ((option & GMN_ARENA) || !(d_info[player_ptr->dungeon_idx].flags1 & DF1_BEGINNER)) {
120         /* Nightmare mode allows more out-of depth monsters */
121         if (ironman_nightmare && !randint0(pls_kakuritu)) {
122             /* What a bizarre calculation */
123             max_level = 1 + (max_level * MAX_DEPTH / randint1(MAX_DEPTH));
124         } else {
125             /* Occasional "nasty" monster */
126             if (!randint0(pls_kakuritu)) {
127                 /* Pick a max_level bonus */
128                 max_level += pls_max_level;
129             }
130         }
131     }
132
133     total = 0L;
134
135     /* Process probabilities */
136     for (i = 0; i < alloc_race_size; i++) {
137         table[i].prob3 = 0;
138         if (table[i].level < min_level)
139             continue;
140         if (max_level < table[i].level)
141             break; // sorted by depth array,
142         r_idx = table[i].index;
143         r_ptr = &r_info[r_idx];
144         if (!(option & GMN_ARENA) && !chameleon_change_m_idx) {
145             if (((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags7 & (RF7_NAZGUL))) && (r_ptr->cur_num >= r_ptr->max_num)) {
146                 continue;
147             }
148
149             if ((r_ptr->flags7 & (RF7_UNIQUE2)) && (r_ptr->cur_num >= 1)) {
150                 continue;
151             }
152
153             if (r_idx == MON_BANORLUPART) {
154                 if (r_info[MON_BANOR].cur_num > 0)
155                     continue;
156                 if (r_info[MON_LUPART].cur_num > 0)
157                     continue;
158             }
159         }
160
161         mon_num++;
162         table[i].prob3 = table[i].prob2;
163         total += table[i].prob3;
164     }
165
166     if (cheat_hear) {
167         msg_format(_("モンスター第3次候補数:%d(%d-%dF)%d ", "monster third selection:%d(%d-%dF)%d "), mon_num, min_level, max_level, total);
168     }
169
170     if (total <= 0)
171         return 0;
172
173     value = randint0(total);
174     int found_count = 0;
175     for (i = 0; i < alloc_race_size; i++) {
176         if (value < table[i].prob3)
177             break;
178         value = value - table[i].prob3;
179         found_count++;
180     }
181
182     p = randint0(100);
183
184     /* Try for a "harder" monster once (50%) or twice (10%) */
185     if (p < 60) {
186         j = found_count;
187         value = randint0(total);
188         for (found_count = 0; found_count < alloc_race_size; found_count++) {
189             if (value < table[found_count].prob3)
190                 break;
191
192             value = value - table[found_count].prob3;
193         }
194
195         if (table[found_count].level < table[j].level)
196             found_count = j;
197     }
198
199     /* Try for a "harder" monster twice (10%) */
200     if (p < 10) {
201         j = found_count;
202         value = randint0(total);
203         for (found_count = 0; found_count < alloc_race_size; found_count++) {
204             if (value < table[found_count].prob3)
205                 break;
206
207             value = value - table[found_count].prob3;
208         }
209
210         if (table[found_count].level < table[j].level)
211             found_count = j;
212     }
213
214     return (table[found_count].index);
215 }
216
217 /*!
218  * @param player_ptr プレーヤーへの参照ポインタ
219  * @brief カメレオンの王の変身対象となるモンスターかどうか判定する / Hack -- the index of the summoning monster
220  * @param r_idx モンスター種族ID
221  * @return 対象にできるならtrueを返す
222  */
223 static bool monster_hook_chameleon_lord(player_type *player_ptr, MONRACE_IDX r_idx)
224 {
225     floor_type *floor_ptr = player_ptr->current_floor_ptr;
226     monster_race *r_ptr = &r_info[r_idx];
227     monster_type *m_ptr = &floor_ptr->m_list[chameleon_change_m_idx];
228     monster_race *old_r_ptr = &r_info[m_ptr->r_idx];
229
230     if (!(r_ptr->flags1 & (RF1_UNIQUE)))
231         return FALSE;
232     if (r_ptr->flags7 & (RF7_FRIENDLY | RF7_CHAMELEON))
233         return FALSE;
234
235     if (ABS(r_ptr->level - r_info[MON_CHAMELEON_K].level) > 5)
236         return FALSE;
237
238     if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE)
239         || (r_ptr->blow[3].method == RBM_EXPLODE))
240         return FALSE;
241
242     if (!monster_can_cross_terrain(player_ptr, floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].feat, r_ptr, 0))
243         return FALSE;
244
245     if (!(old_r_ptr->flags7 & RF7_CHAMELEON)) {
246         if (monster_has_hostile_align(player_ptr, m_ptr, 0, 0, r_ptr))
247             return FALSE;
248     } else if (summon_specific_who > 0) {
249         if (monster_has_hostile_align(player_ptr, &floor_ptr->m_list[summon_specific_who], 0, 0, r_ptr))
250             return FALSE;
251     }
252
253     return TRUE;
254 }
255
256 /*!
257  * @brief カメレオンの変身対象となるモンスターかどうか判定する / Hack -- the index of the summoning monster
258  * @param r_idx モンスター種族ID
259  * @return 対象にできるならtrueを返す
260  * @todo グローバル変数対策の上 monster_hook.cへ移す。
261  */
262 static bool monster_hook_chameleon(player_type *player_ptr, MONRACE_IDX r_idx)
263 {
264     floor_type *floor_ptr = player_ptr->current_floor_ptr;
265     monster_race *r_ptr = &r_info[r_idx];
266     monster_type *m_ptr = &floor_ptr->m_list[chameleon_change_m_idx];
267     monster_race *old_r_ptr = &r_info[m_ptr->r_idx];
268
269     if (r_ptr->flags1 & (RF1_UNIQUE))
270         return FALSE;
271     if (r_ptr->flags2 & RF2_MULTIPLY)
272         return FALSE;
273     if (r_ptr->flags7 & (RF7_FRIENDLY | RF7_CHAMELEON))
274         return FALSE;
275
276     if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE)
277         || (r_ptr->blow[3].method == RBM_EXPLODE))
278         return FALSE;
279
280     if (!monster_can_cross_terrain(player_ptr, floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].feat, r_ptr, 0))
281         return FALSE;
282
283     if (!(old_r_ptr->flags7 & RF7_CHAMELEON)) {
284         if ((old_r_ptr->flags3 & RF3_GOOD) && !(r_ptr->flags3 & RF3_GOOD))
285             return FALSE;
286         if ((old_r_ptr->flags3 & RF3_EVIL) && !(r_ptr->flags3 & RF3_EVIL))
287             return FALSE;
288         if (!(old_r_ptr->flags3 & (RF3_GOOD | RF3_EVIL)) && (r_ptr->flags3 & (RF3_GOOD | RF3_EVIL)))
289             return FALSE;
290     } else if (summon_specific_who > 0) {
291         if (monster_has_hostile_align(player_ptr, &floor_ptr->m_list[summon_specific_who], 0, 0, r_ptr))
292             return FALSE;
293     }
294
295     return (*(get_monster_hook(player_ptr)))(player_ptr, r_idx);
296 }
297
298 /*!
299  * @brief モンスターの変身処理
300  * @param player_ptr プレーヤーへの参照ポインタ
301  * @param m_idx 変身処理を受けるモンスター情報のID
302  * @param born 生成時の初変身先指定ならばtrue
303  * @param r_idx 旧モンスター種族のID
304  * @return なし
305  */
306 void choose_new_monster(player_type *player_ptr, MONSTER_IDX m_idx, bool born, MONRACE_IDX r_idx)
307 {
308     floor_type *floor_ptr = player_ptr->current_floor_ptr;
309     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
310     monster_race *r_ptr;
311
312     bool old_unique = FALSE;
313     if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE)
314         old_unique = TRUE;
315     if (old_unique && (r_idx == MON_CHAMELEON))
316         r_idx = MON_CHAMELEON_K;
317     r_ptr = &r_info[r_idx];
318
319     char old_m_name[MAX_NLEN];
320     monster_desc(player_ptr, old_m_name, m_ptr, 0);
321
322     if (!r_idx) {
323         DEPTH level;
324
325         chameleon_change_m_idx = m_idx;
326         if (old_unique)
327             get_mon_num_prep(player_ptr, monster_hook_chameleon_lord, NULL);
328         else
329             get_mon_num_prep(player_ptr, monster_hook_chameleon, NULL);
330
331         if (old_unique)
332             level = r_info[MON_CHAMELEON_K].level;
333         else if (!floor_ptr->dun_level)
334             level = wilderness[player_ptr->wilderness_y][player_ptr->wilderness_x].level;
335         else
336             level = floor_ptr->dun_level;
337
338         if (d_info[player_ptr->dungeon_idx].flags1 & DF1_CHAMELEON)
339             level += 2 + randint1(3);
340
341         r_idx = get_mon_num(player_ptr, 0, level, 0);
342         r_ptr = &r_info[r_idx];
343
344         chameleon_change_m_idx = 0;
345         if (!r_idx)
346             return;
347     }
348
349     m_ptr->r_idx = r_idx;
350     m_ptr->ap_r_idx = r_idx;
351     update_monster(player_ptr, m_idx, FALSE);
352     lite_spot(player_ptr, m_ptr->fy, m_ptr->fx);
353
354     int old_r_idx = m_ptr->r_idx;
355     if ((r_info[old_r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK)) || (r_ptr->flags7 & (RF7_LITE_MASK | RF7_DARK_MASK)))
356         player_ptr->update |= (PU_MON_LITE);
357
358     if (born) {
359         if (r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)) {
360             m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
361             if (r_ptr->flags3 & RF3_EVIL)
362                 m_ptr->sub_align |= SUB_ALIGN_EVIL;
363             if (r_ptr->flags3 & RF3_GOOD)
364                 m_ptr->sub_align |= SUB_ALIGN_GOOD;
365         }
366
367         return;
368     }
369
370     if (m_idx == player_ptr->riding) {
371         GAME_TEXT m_name[MAX_NLEN];
372         monster_desc(player_ptr, m_name, m_ptr, 0);
373         msg_format(_("突然%sが変身した。", "Suddenly, %s transforms!"), old_m_name);
374         if (!(r_ptr->flags7 & RF7_RIDING))
375             if (process_fall_off_horse(player_ptr, 0, TRUE))
376                 msg_format(_("地面に落とされた。", "You have fallen from %s."), m_name);
377     }
378
379     m_ptr->mspeed = get_mspeed(floor_ptr, r_ptr);
380
381     int oldmaxhp = m_ptr->max_maxhp;
382     if (r_ptr->flags1 & RF1_FORCE_MAXHP) {
383         m_ptr->max_maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
384     } else {
385         m_ptr->max_maxhp = damroll(r_ptr->hdice, r_ptr->hside);
386     }
387
388     if (ironman_nightmare) {
389         u32b hp = m_ptr->max_maxhp * 2L;
390         m_ptr->max_maxhp = (HIT_POINT)MIN(30000, hp);
391     }
392
393     m_ptr->maxhp = (long)(m_ptr->maxhp * m_ptr->max_maxhp) / oldmaxhp;
394     if (m_ptr->maxhp < 1)
395         m_ptr->maxhp = 1;
396     m_ptr->hp = (long)(m_ptr->hp * m_ptr->max_maxhp) / oldmaxhp;
397     m_ptr->dealt_damage = 0;
398 }
399
400 /*!
401  * @brief モンスターの個体加速を設定する / Get initial monster speed
402  * @param r_ptr モンスター種族の参照ポインタ
403  * @return 加速値
404  */
405 SPEED get_mspeed(floor_type *floor_ptr, monster_race *r_ptr)
406 {
407     SPEED mspeed = r_ptr->speed;
408     if (!(r_ptr->flags1 & RF1_UNIQUE) && !floor_ptr->inside_arena) {
409         /* Allow some small variation per monster */
410         int i = SPEED_TO_ENERGY(r_ptr->speed) / (one_in_(4) ? 3 : 10);
411         if (i)
412             mspeed += rand_spread(0, i);
413     }
414
415     if (mspeed > 199)
416         mspeed = 199;
417
418     return mspeed;
419 }
420
421 /*!
422  * @brief 指定したモンスターに隣接しているモンスターの数を返す。
423  * / Count number of adjacent monsters
424  * @param player_ptr プレーヤーへの参照ポインタ
425  * @param m_idx 隣接数を調べたいモンスターのID
426  * @return 隣接しているモンスターの数
427  */
428 int get_monster_crowd_number(floor_type *floor_ptr, MONSTER_IDX m_idx)
429 {
430     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
431     POSITION my = m_ptr->fy;
432     POSITION mx = m_ptr->fx;
433     int count = 0;
434     for (int i = 0; i < 7; i++) {
435         int ay = my + ddy_ddd[i];
436         int ax = mx + ddx_ddd[i];
437
438         if (!in_bounds(floor_ptr, ay, ax))
439             continue;
440         if (floor_ptr->grid_array[ay][ax].m_idx > 0)
441             count++;
442     }
443
444     return count;
445 }