OSDN Git Service

67e9d99bcf4b4f53d4300582cdeda8f8c6e3c41e
[hengband/hengband.git] / src / monster-floor / monster-generator.c
1 /*!
2  * todo 後で再分割する
3  * @brief モンスター生成処理
4  * @date 2020/06/10
5  * @author Hourier
6  */
7
8 #include "monster-floor/monster-generator.h"
9 #include "dungeon/dungeon.h"
10 #include "floor/floor.h"
11 #include "main/sound-definitions-table.h"
12 #include "monster-floor/one-monster-placer.h"
13 #include "monster-floor/place-monster-types.h"
14 #include "monster-race/monster-race-hook.h"
15 #include "monster-race/race-flags1.h"
16 #include "monster-race/race-flags7.h"
17 #include "monster-race/race-indice-types.h"
18 #include "monster/monster-flag-types.h"
19 #include "monster/monster-info.h"
20 #include "monster/monster-list.h"
21 #include "monster/monster-util.h"
22 #include "monster/smart-learn-types.h"
23 #include "mspell/summon-checker.h"
24 #include "spell/spells-summon.h"
25
26 #define MON_SCAT_MAXD 10 /*!< mon_scatter()関数によるモンスター配置で許される中心からの最大距離 */
27
28 /*!
29  * @var place_monster_idx
30  * @brief 護衛対象となるモンスター種族IDを渡すグローバル変数 / Hack -- help pick an escort type
31  * @todo 関数ポインタの都合を配慮しながら、グローバル変数place_monster_idxを除去し、関数引数化する
32  */
33 static MONSTER_IDX place_monster_idx = 0;
34
35 /*!
36  * @var place_monster_m_idx
37  * @brief 護衛対象となるモンスターIDを渡すグローバル変数 / Hack -- help pick an escort type
38  * @todo 関数ポインタの都合を配慮しながら、グローバル変数place_monster_m_idxを除去し、関数引数化する
39  */
40 static MONSTER_IDX place_monster_m_idx = 0;
41
42 /*!
43  * @var summon_specific_who
44  * @brief 召喚を行ったプレイヤーあるいはモンスターのIDを示すグローバル変数 / Hack -- the index of the summoning monster
45  * @todo summon_specific_who グローバル変数の除去と関数引数への代替を行う
46  */
47 int summon_specific_who = -1;
48
49 /*!
50  * @var summon_unique_okay
51  * @brief 召喚対象にユニークを含めるかを示すグローバル変数 / summoning unique enable
52  * @todo summon_unique_okay グローバル変数の除去と関数引数への代替を行う
53  */
54 bool summon_unique_okay = FALSE;
55
56 /*!
57  * @brief モンスター1体を目標地点に可能な限り近い位置に生成する / improved version of scatter() for place monster
58  * @param player_ptr プレーヤーへの参照ポインタ
59  * @param r_idx 生成モンスター種族
60  * @param yp 結果生成位置y座標
61  * @param xp 結果生成位置x座標
62  * @param y 中心生成位置y座標
63  * @param x 中心生成位置x座標
64  * @param max_dist 生成位置の最大半径
65  * @return 成功したらtrue
66  *
67  */
68 static bool mon_scatter(player_type *player_ptr, MONRACE_IDX r_idx, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION max_dist)
69 {
70     POSITION place_x[MON_SCAT_MAXD];
71     POSITION place_y[MON_SCAT_MAXD];
72     int num[MON_SCAT_MAXD];
73
74     if (max_dist >= MON_SCAT_MAXD)
75         return FALSE;
76
77     int i;
78     for (i = 0; i < MON_SCAT_MAXD; i++)
79         num[i] = 0;
80
81     floor_type *floor_ptr = player_ptr->current_floor_ptr;
82     for (POSITION nx = x - max_dist; nx <= x + max_dist; nx++) {
83         for (POSITION ny = y - max_dist; ny <= y + max_dist; ny++) {
84             if (!in_bounds(floor_ptr, ny, nx))
85                 continue;
86             if (!projectable(player_ptr, y, x, ny, nx))
87                 continue;
88             if (r_idx > 0) {
89                 monster_race *r_ptr = &r_info[r_idx];
90                 if (!monster_can_enter(player_ptr, ny, nx, r_ptr, 0))
91                     continue;
92             } else {
93                 if (!is_cave_empty_bold2(player_ptr, ny, nx))
94                     continue;
95                 if (pattern_tile(floor_ptr, ny, nx))
96                     continue;
97             }
98
99             i = distance(y, x, ny, nx);
100             if (i > max_dist)
101                 continue;
102
103             num[i]++;
104             if (one_in_(num[i])) {
105                 place_x[i] = nx;
106                 place_y[i] = ny;
107             }
108         }
109     }
110
111     i = 0;
112     while (i < MON_SCAT_MAXD && 0 == num[i])
113         i++;
114     if (i >= MON_SCAT_MAXD)
115         return FALSE;
116
117     *xp = place_x[i];
118     *yp = place_y[i];
119
120     return TRUE;
121 }
122
123 /*!
124  * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
125  * @brief モンスターが召喚の基本条件に合っているかをチェックする / Hack -- help decide if a monster race is "okay" to summon
126  * @param r_idx チェックするモンスター種族ID
127  * @return 召喚対象にできるならばTRUE
128  */
129 static bool summon_specific_okay(MONRACE_IDX r_idx)
130 {
131     monster_race *r_ptr = &r_info[r_idx];
132     monster_type *m_ptr = &p_ptr->current_floor_ptr->m_list[summon_specific_who];
133     if (!mon_hook_dungeon(r_idx))
134         return FALSE;
135
136     if (summon_specific_who > 0) {
137         if (monster_has_hostile_align(p_ptr, m_ptr, 0, 0, r_ptr))
138             return FALSE;
139     } else if (summon_specific_who < 0) {
140         if (monster_has_hostile_align(p_ptr, NULL, 10, -10, r_ptr)) {
141             if (!one_in_(ABS(p_ptr->align) / 2 + 1))
142                 return FALSE;
143         }
144     }
145
146     if (!summon_unique_okay && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)))
147         return FALSE;
148
149     if (!summon_specific_type)
150         return TRUE;
151
152     if ((summon_specific_who < 0) && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) && monster_has_hostile_align(p_ptr, NULL, 10, -10, r_ptr))
153         return FALSE;
154
155     if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[p_ptr->dungeon_idx].flags1 & DF1_CHAMELEON))
156         return TRUE;
157
158     return (check_summon_specific(p_ptr, m_ptr->r_idx, r_idx));
159 }
160
161 /*!
162  * @brief モンスターを召喚により配置する / Place a monster (of the specified "type") near the given location. Return TRUE if a monster was actually summoned.
163  * @param player_ptr プレーヤーへの参照ポインタ
164  * @param who 召喚主のモンスター情報ID
165  * @param y1 目標地点y座標
166  * @param x1 目標地点x座標
167  * @param lev 相当生成階
168  * @param type 召喚種別
169  * @param mode 生成オプション
170  * @return 召喚できたらtrueを返す
171  */
172 bool summon_specific(player_type *player_ptr, MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, int type, BIT_FLAGS mode)
173 {
174     floor_type *floor_ptr = player_ptr->current_floor_ptr;
175     if (floor_ptr->inside_arena)
176         return FALSE;
177
178     POSITION x, y;
179     if (!mon_scatter(player_ptr, 0, &y, &x, y1, x1, 2))
180         return FALSE;
181
182     summon_specific_who = who;
183     summon_specific_type = type;
184     summon_unique_okay = (mode & PM_ALLOW_UNIQUE) ? TRUE : FALSE;
185     get_mon_num_prep(player_ptr, summon_specific_okay, get_monster_hook2(player_ptr, y, x));
186
187     MONRACE_IDX r_idx = get_mon_num(player_ptr, (floor_ptr->dun_level + lev) / 2 + 5, 0);
188     if (!r_idx) {
189         summon_specific_type = 0;
190         return FALSE;
191     }
192
193     if ((type == SUMMON_BLUE_HORROR) || (type == SUMMON_DAWN))
194         mode |= PM_NO_KAGE;
195
196     if (!place_monster_aux(player_ptr, who, y, x, r_idx, mode)) {
197         summon_specific_type = 0;
198         return FALSE;
199     }
200
201     summon_specific_type = 0;
202     sound(SOUND_SUMMON);
203     return TRUE;
204 }
205
206 /*!
207  * @brief 特定モンスター種族を召喚により生成する / A "dangerous" function, creates a pet of the specified type
208  * @param player_ptr プレーヤーへの参照ポインタ
209  * @param who 召喚主のモンスター情報ID
210  * @param oy 目標地点y座標
211  * @param ox 目標地点x座標
212  * @param r_idx 生成するモンスター種族ID
213  * @param mode 生成オプション
214  * @return 召喚できたらtrueを返す
215  */
216 bool summon_named_creature(player_type *player_ptr, MONSTER_IDX who, POSITION oy, POSITION ox, MONRACE_IDX r_idx, BIT_FLAGS mode)
217 {
218     if (r_idx >= max_r_idx)
219         return FALSE;
220
221     POSITION x, y;
222     if (player_ptr->current_floor_ptr->inside_arena)
223         return FALSE;
224
225     if (!mon_scatter(player_ptr, r_idx, &y, &x, oy, ox, 2))
226         return FALSE;
227
228     return place_monster_aux(player_ptr, who, y, x, r_idx, (mode | PM_NO_KAGE));
229 }
230
231 /*!
232  * @brief モンスターを増殖生成する / Let the given monster attempt to reproduce.
233  * @param player_ptr プレーヤーへの参照ポインタ
234  * @param m_idx 増殖するモンスター情報ID
235  * @param clone クローン・モンスター処理ならばtrue
236  * @param mode 生成オプション
237  * @return 生成できたらtrueを返す
238  * @details
239  * Note that "reproduction" REQUIRES empty space.
240  */
241 bool multiply_monster(player_type *player_ptr, MONSTER_IDX m_idx, bool clone, BIT_FLAGS mode)
242 {
243     floor_type *floor_ptr = player_ptr->current_floor_ptr;
244     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
245     POSITION y, x;
246     if (!mon_scatter(player_ptr, m_ptr->r_idx, &y, &x, m_ptr->fy, m_ptr->fx, 1))
247         return FALSE;
248
249     if (m_ptr->mflag2 & MFLAG2_NOPET)
250         mode |= PM_NO_PET;
251
252     if (!place_monster_aux(player_ptr, m_idx, y, x, m_ptr->r_idx, (mode | PM_NO_KAGE | PM_MULTIPLY)))
253         return FALSE;
254
255     if (clone || (m_ptr->smart & SM_CLONED)) {
256         floor_ptr->m_list[hack_m_idx_ii].smart |= SM_CLONED;
257         floor_ptr->m_list[hack_m_idx_ii].mflag2 |= MFLAG2_NOPET;
258     }
259
260     return TRUE;
261 }
262
263 /*!
264  * @brief モンスターを目標地点に集団生成する / Attempt to place a "group" of monsters around the given location
265  * @param who 召喚主のモンスター情報ID
266  * @param y 中心生成位置y座標
267  * @param x 中心生成位置x座標
268  * @param r_idx 生成モンスター種族
269  * @param mode 生成オプション
270  * @return 成功したらtrue
271  */
272 static bool place_monster_group(player_type *player_ptr, MONSTER_IDX who, POSITION y, POSITION x, MONRACE_IDX r_idx, BIT_FLAGS mode)
273 {
274     monster_race *r_ptr = &r_info[r_idx];
275     int total = randint1(10);
276
277     floor_type *floor_ptr = player_ptr->current_floor_ptr;
278     int extra = 0;
279     if (r_ptr->level > floor_ptr->dun_level) {
280         extra = r_ptr->level - floor_ptr->dun_level;
281         extra = 0 - randint1(extra);
282     } else if (r_ptr->level < floor_ptr->dun_level) {
283         extra = floor_ptr->dun_level - r_ptr->level;
284         extra = randint1(extra);
285     }
286
287     if (extra > 9)
288         extra = 9;
289
290     total += extra;
291
292     if (total < 1)
293         total = 1;
294     if (total > GROUP_MAX)
295         total = GROUP_MAX;
296
297     int hack_n = 1;
298     POSITION hack_x[GROUP_MAX];
299     hack_x[0] = x;
300     POSITION hack_y[GROUP_MAX];
301     hack_y[0] = y;
302
303     for (int n = 0; (n < hack_n) && (hack_n < total); n++) {
304         POSITION hx = hack_x[n];
305         POSITION hy = hack_y[n];
306         for (int i = 0; (i < 8) && (hack_n < total); i++) {
307             POSITION mx, my;
308             scatter(player_ptr, &my, &mx, hy, hx, 4, 0);
309             if (!is_cave_empty_bold2(player_ptr, my, mx))
310                 continue;
311
312             if (place_monster_one(player_ptr, who, my, mx, r_idx, mode)) {
313                 hack_y[hack_n] = my;
314                 hack_x[hack_n] = mx;
315                 hack_n++;
316             }
317         }
318     }
319
320     return TRUE;
321 }
322
323 /*!
324  * todo ここには本来floor_type*を追加したいが、monster.hにfloor.hの参照を追加するとコンパイルエラーが出るので保留
325  * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
326  * @brief モンスター種族が召喚主の護衛となれるかどうかをチェックする / Hack -- help pick an escort type
327  * @param r_idx チェックするモンスター種族のID
328  * @return 護衛にできるならばtrue
329  */
330 static bool place_monster_can_escort(MONRACE_IDX r_idx)
331 {
332     monster_race *r_ptr = &r_info[place_monster_idx];
333     monster_type *m_ptr = &p_ptr->current_floor_ptr->m_list[place_monster_m_idx];
334     monster_race *z_ptr = &r_info[r_idx];
335
336     if (mon_hook_dungeon(place_monster_idx) != mon_hook_dungeon(r_idx))
337         return FALSE;
338     if (z_ptr->d_char != r_ptr->d_char)
339         return FALSE;
340     if (z_ptr->level > r_ptr->level)
341         return FALSE;
342     if (z_ptr->flags1 & RF1_UNIQUE)
343         return FALSE;
344     if (place_monster_idx == r_idx)
345         return FALSE;
346     if (monster_has_hostile_align(p_ptr, m_ptr, 0, 0, z_ptr))
347         return FALSE;
348
349     if (r_ptr->flags7 & RF7_FRIENDLY) {
350         if (monster_has_hostile_align(p_ptr, NULL, 1, -1, z_ptr))
351             return FALSE;
352     }
353
354     if ((r_ptr->flags7 & RF7_CHAMELEON) && !(z_ptr->flags7 & RF7_CHAMELEON))
355         return FALSE;
356
357     return TRUE;
358 }
359
360 /*!
361  * @brief 一般的なモンスター生成処理のサブルーチン / Attempt to place a monster of the given race at the given location
362  * @param player_ptr プレーヤーへの参照ポインタ
363  * @param who 召喚主のモンスター情報ID
364  * @param y 生成地点y座標
365  * @param x 生成地点x座標
366  * @param r_idx 生成するモンスターの種族ID
367  * @param mode 生成オプション
368  * @return 生成に成功したらtrue
369  */
370 bool place_monster_aux(player_type *player_ptr, MONSTER_IDX who, POSITION y, POSITION x, MONRACE_IDX r_idx, BIT_FLAGS mode)
371 {
372     monster_race *r_ptr = &r_info[r_idx];
373
374     if (!(mode & PM_NO_KAGE) && one_in_(333))
375         mode |= PM_KAGE;
376
377     if (!place_monster_one(player_ptr, who, y, x, r_idx, mode))
378         return FALSE;
379     if (!(mode & PM_ALLOW_GROUP))
380         return TRUE;
381
382     place_monster_m_idx = hack_m_idx_ii;
383
384     /* Reinforcement */
385     for (int i = 0; i < 6; i++) {
386         if (!r_ptr->reinforce_id[i])
387             break;
388         int n = damroll(r_ptr->reinforce_dd[i], r_ptr->reinforce_ds[i]);
389         for (int j = 0; j < n; j++) {
390             POSITION nx, ny, d = 7;
391             scatter(player_ptr, &ny, &nx, y, x, d, 0);
392             (void)place_monster_one(player_ptr, place_monster_m_idx, ny, nx, r_ptr->reinforce_id[i], mode);
393         }
394     }
395
396     if (r_ptr->flags1 & (RF1_FRIENDS)) {
397         (void)place_monster_group(player_ptr, who, y, x, r_idx, mode);
398     }
399
400     if (!(r_ptr->flags1 & (RF1_ESCORT)))
401         return TRUE;
402
403     place_monster_idx = r_idx;
404     for (int i = 0; i < 32; i++) {
405         POSITION nx, ny, d = 3;
406         MONRACE_IDX z;
407         scatter(player_ptr, &ny, &nx, y, x, d, 0);
408         if (!is_cave_empty_bold2(player_ptr, ny, nx))
409             continue;
410
411         get_mon_num_prep(player_ptr, place_monster_can_escort, get_monster_hook2(player_ptr, ny, nx));
412         z = get_mon_num(player_ptr, r_ptr->level, 0);
413         if (!z)
414             break;
415
416         (void)place_monster_one(player_ptr, place_monster_m_idx, ny, nx, z, mode);
417         if ((r_info[z].flags1 & RF1_FRIENDS) || (r_ptr->flags1 & RF1_ESCORTS)) {
418             (void)place_monster_group(player_ptr, place_monster_m_idx, ny, nx, z, mode);
419         }
420     }
421
422     return TRUE;
423 }
424
425 /*!
426  * @brief 一般的なモンスター生成処理のメインルーチン / Attempt to place a monster of the given race at the given location
427  * @param player_ptr プレーヤーへの参照ポインタ
428  * @param y 生成地点y座標
429  * @param x 生成地点x座標
430  * @param mode 生成オプション
431  * @return 生成に成功したらtrue
432  */
433 bool place_monster(player_type *player_ptr, POSITION y, POSITION x, BIT_FLAGS mode)
434 {
435     MONRACE_IDX r_idx;
436     get_mon_num_prep(player_ptr, get_monster_hook(player_ptr), get_monster_hook2(player_ptr, y, x));
437     r_idx = get_mon_num(player_ptr, player_ptr->current_floor_ptr->monster_level, 0);
438     if (!r_idx)
439         return FALSE;
440
441     if ((one_in_(5) || (player_ptr->current_floor_ptr->base_level == 0)) && !(r_info[r_idx].flags1 & RF1_UNIQUE)
442         && my_strchr("hkoptuyAHLOPTUVY", r_info[r_idx].d_char)) {
443         mode |= PM_JURAL;
444     }
445
446     if (place_monster_aux(player_ptr, 0, y, x, r_idx, mode))
447         return TRUE;
448
449     return FALSE;
450 }
451
452 /*!
453  * @brief 指定地点に1種類のモンスター種族による群れを生成する
454  * @param player_ptr プレーヤーへの参照ポインタ
455  * @param y 生成地点y座標
456  * @param x 生成地点x座標
457  * @return 生成に成功したらtrue
458  */
459 bool alloc_horde(player_type *player_ptr, POSITION y, POSITION x)
460 {
461     get_mon_num_prep(player_ptr, get_monster_hook(player_ptr), get_monster_hook2(player_ptr, y, x));
462
463     floor_type *floor_ptr = player_ptr->current_floor_ptr;
464     MONRACE_IDX r_idx = 0;
465     int attempts = 1000;
466     monster_race *r_ptr = NULL;
467     while (--attempts) {
468         r_idx = get_mon_num(player_ptr, floor_ptr->monster_level, 0);
469         if (!r_idx)
470             return FALSE;
471
472         r_ptr = &r_info[r_idx];
473         if (r_ptr->flags1 & RF1_UNIQUE)
474             continue;
475
476         if (r_idx == MON_HAGURE)
477             continue;
478         break;
479     }
480
481     if (attempts < 1)
482         return FALSE;
483
484     attempts = 1000;
485
486     while (--attempts) {
487         if (place_monster_aux(player_ptr, 0, y, x, r_idx, 0L))
488             break;
489     }
490
491     if (attempts < 1)
492         return FALSE;
493
494     MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
495     if (floor_ptr->m_list[m_idx].mflag2 & MFLAG2_CHAMELEON)
496         r_ptr = &r_info[floor_ptr->m_list[m_idx].r_idx];
497
498     POSITION cy = y;
499     POSITION cx = x;
500     for (attempts = randint1(10) + 5; attempts; attempts--) {
501         scatter(player_ptr, &cy, &cx, y, x, 5, 0);
502         (void)summon_specific(player_ptr, m_idx, cy, cx, floor_ptr->dun_level + 5, SUMMON_KIN, PM_ALLOW_GROUP);
503         y = cy;
504         x = cx;
505     }
506
507     if (cheat_hear)
508         msg_format(_("モンスターの大群(%c)", "Monster horde (%c)."), r_ptr->d_char);
509     return TRUE;
510 }
511
512 /*!
513  * @brief ダンジョンの主生成を試みる / Put the Guardian
514  * @param player_ptr プレーヤーへの参照ポインタ
515  * @param def_val 現在の主の生成状態
516  * @return 生成に成功したらtrue
517  */
518 bool alloc_guardian(player_type *player_ptr, bool def_val)
519 {
520     MONRACE_IDX guardian = d_info[player_ptr->dungeon_idx].final_guardian;
521     floor_type *floor_ptr = player_ptr->current_floor_ptr;
522     bool is_guardian_applicable = guardian > 0;
523     is_guardian_applicable &= d_info[player_ptr->dungeon_idx].maxdepth == floor_ptr->dun_level;
524     is_guardian_applicable &= r_info[guardian].cur_num < r_info[guardian].max_num;
525     if (!is_guardian_applicable)
526         return def_val;
527
528     int try_count = 4000;
529     while (try_count) {
530         POSITION oy = randint1(floor_ptr->height - 4) + 2;
531         POSITION ox = randint1(floor_ptr->width - 4) + 2;
532         if (!is_cave_empty_bold2(player_ptr, oy, ox)) {
533             try_count++;
534             continue;
535         }
536
537         if (!monster_can_cross_terrain(player_ptr, floor_ptr->grid_array[oy][ox].feat, &r_info[guardian], 0)) {
538             try_count++;
539             continue;
540         }
541
542         if (place_monster_aux(player_ptr, 0, oy, ox, guardian, (PM_ALLOW_GROUP | PM_NO_KAGE | PM_NO_PET)))
543             return TRUE;
544
545         try_count--;
546     }
547
548     return FALSE;
549 }
550
551 /*!
552  * @brief ダンジョンの初期配置モンスターを生成1回生成する / Attempt to allocate a random monster in the dungeon.
553  * @param dis プレイヤーから離れるべき最低距離
554  * @param mode 生成オプション
555  * @return 生成に成功したらtrue
556  * @details
557  * Place the monster at least "dis" distance from the player.
558  * Use "slp" to choose the initial "sleep" status
559  * Use "floor_ptr->monster_level" for the monster level
560  */
561 bool alloc_monster(player_type *player_ptr, POSITION dis, BIT_FLAGS mode)
562 {
563     if (alloc_guardian(player_ptr, FALSE))
564         return TRUE;
565
566     floor_type *floor_ptr = player_ptr->current_floor_ptr;
567     POSITION y = 0, x = 0;
568     int attempts_left = 10000;
569     while (attempts_left--) {
570         y = randint0(floor_ptr->height);
571         x = randint0(floor_ptr->width);
572
573         if (floor_ptr->dun_level) {
574             if (!is_cave_empty_bold2(player_ptr, y, x))
575                 continue;
576         } else {
577             if (!is_cave_empty_bold(player_ptr, y, x))
578                 continue;
579         }
580
581         if (distance(y, x, player_ptr->y, player_ptr->x) > dis)
582             break;
583     }
584
585     if (!attempts_left) {
586         if (cheat_xtra || cheat_hear) {
587             msg_print(_("警告!新たなモンスターを配置できません。小さい階ですか?", "Warning! Could not allocate a new monster. Small level?"));
588         }
589
590         return FALSE;
591     }
592
593     if (randint1(5000) <= floor_ptr->dun_level) {
594         if (alloc_horde(player_ptr, y, x)) {
595             return TRUE;
596         }
597     } else {
598         if (place_monster(player_ptr, y, x, (mode | PM_ALLOW_GROUP)))
599             return TRUE;
600     }
601
602     return FALSE;
603 }