OSDN Git Service

[Refactor] #40577 Separated door.c/h from floor.c/h
[hengband/hengband.git] / src / room / rooms-pit-nest.c
1 #include "room/rooms-pit-nest.h"
2 #include "dungeon/dungeon.h"
3 #include "floor/floor-generator.h"
4 #include "game-option/cheat-options.h"
5 #include "game-option/cheat-types.h"
6 #include "grid/door.h"
7 #include "grid/feature.h"
8 #include "grid/grid.h"
9 #include "monster-floor/monster-generator.h"
10 #include "monster-floor/place-monster-types.h"
11 #include "monster-race/monster-race-hook.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags-resistance.h"
14 #include "monster-race/race-flags1.h"
15 #include "monster-race/race-flags2.h"
16 #include "monster-race/race-flags3.h"
17 #include "monster-race/race-flags4.h"
18 #include "monster-race/race-flags7.h"
19 #include "monster/monster-info.h"
20 #include "monster/monster-list.h"
21 #include "monster/monster-util.h"
22 #include "room/pit-nest-kinds-table.h"
23 #include "room/space-finder.h"
24 #include "system/floor-type-definition.h"
25 #include "util/sort.h"
26 #include "view/display-messages.h"
27 #include "wizard/wizard-messages.h"
28
29 /*!
30 * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める
31 * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ
32 * @param allow_flag_mask 生成が許されるpit/nestのビット配列
33 * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。
34 */
35 static int pick_vault_type(floor_type *floor_ptr, vault_aux_type *l_ptr, BIT_FLAGS16 allow_flag_mask)
36 {
37         int tmp, total, count;
38
39         vault_aux_type *n_ptr;
40
41         /* Calculate the total possibilities */
42         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
43         {
44                 /* Note end */
45                 if (!n_ptr->name) break;
46
47                 /* Ignore excessive depth */
48                 if (n_ptr->level > floor_ptr->dun_level) continue;
49
50                 /* Not matched with pit/nest flag */
51                 if (!(allow_flag_mask & (1L << count))) continue;
52
53                 /* Count this possibility */
54                 total += n_ptr->chance * MAX_DEPTH / (MIN(floor_ptr->dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
55         }
56
57         /* Pick a random type */
58         tmp = randint0(total);
59
60         /* Find this type */
61         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
62         {
63                 /* Note end */
64                 if (!n_ptr->name) break;
65
66                 /* Ignore excessive depth */
67                 if (n_ptr->level > floor_ptr->dun_level) continue;
68
69                 /* Not matched with pit/nest flag */
70                 if (!(allow_flag_mask & (1L << count))) continue;
71
72                 /* Count this possibility */
73                 total += n_ptr->chance * MAX_DEPTH / (MIN(floor_ptr->dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
74
75                 /* Found the type */
76                 if (tmp < total) break;
77         }
78
79         return n_ptr->name ? count : -1;
80 }
81
82
83 /*!
84 * @brief デバッグ時に生成されたpit/nestの型を出力する処理
85 * @param type pit/nestの型ID
86 * @param nest TRUEならばnest、FALSEならばpit
87 * @return デバッグ表示文字列の参照ポインタ
88 * @details
89 * Hack -- Get the string describing subtype of pit/nest
90 * Determined in prepare function (some pit/nest only)
91 */
92 static concptr pit_subtype_string(int type, bool nest)
93 {
94         static char inner_buf[256] = "";
95
96         inner_buf[0] = '\0'; /* Init string */
97
98         if (nest) /* Nests */
99         {
100                 switch (type)
101                 {
102                 case NEST_TYPE_CLONE:
103                         sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
104                         break;
105                 case NEST_TYPE_SYMBOL_GOOD:
106                 case NEST_TYPE_SYMBOL_EVIL:
107                         sprintf(inner_buf, "(%c)", vault_aux_char);
108                         break;
109                 }
110         }
111         else /* Pits */
112         {
113                 switch (type)
114                 {
115                 case PIT_TYPE_SYMBOL_GOOD:
116                 case PIT_TYPE_SYMBOL_EVIL:
117                         sprintf(inner_buf, "(%c)", vault_aux_char);
118                         break;
119                 case PIT_TYPE_DRAGON:
120                         switch (vault_aux_dragon_mask4)
121                         {
122                         case RF4_BR_ACID: strcpy(inner_buf, _("(酸)", "(acid)"));   break;
123                         case RF4_BR_ELEC: strcpy(inner_buf, _("(稲妻)", "(lightning)")); break;
124                         case RF4_BR_FIRE: strcpy(inner_buf, _("(火炎)", "(fire)")); break;
125                         case RF4_BR_COLD: strcpy(inner_buf, _("(冷気)", "(frost)")); break;
126                         case RF4_BR_POIS: strcpy(inner_buf, _("(毒)", "(poison)"));   break;
127                         case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS) :
128                                 strcpy(inner_buf, _("(万色)", "(multi-hued)")); break;
129                         default: strcpy(inner_buf, _("(未定義)", "(undefined)")); break;
130                         }
131                         break;
132                 }
133         }
134
135         return inner_buf;
136 }
137
138
139 /*
140 *! @brief nestのモンスターリストをソートするための関数 /
141 *  Comp function for sorting nest monster information
142 *  @param u ソート処理対象配列ポインタ
143 *  @param v 未使用
144 *  @param a 比較対象参照ID1
145 *  @param b 比較対象参照ID2
146 *  TODO: to sort.c
147 */
148 static bool ang_sort_comp_nest_mon_info(player_type *player_ptr, vptr u, vptr v, int a, int b)
149 {
150     /* Unused */
151     (void)player_ptr;
152     (void)v;
153
154     nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
155         MONSTER_IDX w1 = nest_mon_info[a].r_idx;
156         MONSTER_IDX w2 = nest_mon_info[b].r_idx;
157         monster_race *r1_ptr = &r_info[w1];
158         monster_race *r2_ptr = &r_info[w2];
159         int z1, z2;
160
161         /* Extract used info */
162         z1 = nest_mon_info[a].used;
163         z2 = nest_mon_info[b].used;
164
165         /* Compare used status */
166         if (z1 < z2) return FALSE;
167         if (z1 > z2) return TRUE;
168
169         /* Compare levels */
170         if (r1_ptr->level < r2_ptr->level) return TRUE;
171         if (r1_ptr->level > r2_ptr->level) return FALSE;
172
173         /* Compare experience */
174         if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
175         if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
176
177         /* Compare indexes */
178         return w1 <= w2;
179 }
180
181
182 /*!
183 * @brief nestのモンスターリストをスワップするための関数 /
184 * Swap function for sorting nest monster information
185 * @param u スワップ処理対象配列ポインタ
186 * @param v 未使用
187 * @param a スワップ対象参照ID1
188 * @param b スワップ対象参照ID2
189 * TODO: to sort.c
190 */
191 static void ang_sort_swap_nest_mon_info(player_type *player_ptr, vptr u, vptr v, int a, int b)
192 {
193     /* Unused */
194     (void)player_ptr;
195     (void)v;
196
197     nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
198         nest_mon_info_type holder;
199
200         /* Swap */
201         holder = nest_mon_info[a];
202         nest_mon_info[a] = nest_mon_info[b];
203         nest_mon_info[b] = holder;
204 }
205
206
207 /*!
208 * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests
209 * @param player_ptr プレーヤーへの参照ポインタ
210 * @return なし
211 * @details
212 * A monster nest is a "big" room, with an "inner" room, containing\n
213 * a "collection" of monsters of a given type strewn about the room.\n
214 *\n
215 * The monsters are chosen from a set of 64 randomly selected monster\n
216 * races, to allow the nest creation to fail instead of having "holes".\n
217 *\n
218 * Note the use of the "get_mon_num_prep()" function, and the special\n
219 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
220 * allocation table" in such a way as to optimize the selection of\n
221 * "appropriate" non-unique monsters for the nest.\n
222 *\n
223 * Note that the "get_mon_num()" function may (rarely) fail, in which\n
224 * case the nest will be empty.\n
225 *\n
226 * Note that "monster nests" will never contain "unique" monsters.\n
227 */
228 bool build_type5(player_type *player_ptr, dun_data_type *dd_ptr)
229 {
230         POSITION y, x, y1, x1, y2, x2, xval, yval;
231         int i;
232         nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
233
234         monster_type align;
235
236         grid_type *g_ptr;
237
238         floor_type *floor_ptr = player_ptr->current_floor_ptr;
239         int cur_nest_type = pick_vault_type(floor_ptr, nest_types, d_info[floor_ptr->dungeon_idx].nest);
240         vault_aux_type *n_ptr;
241
242         /* No type available */
243         if (cur_nest_type < 0) return FALSE;
244
245         n_ptr = &nest_types[cur_nest_type];
246
247         /* Process a preparation function if necessary */
248         if (n_ptr->prep_func) (*(n_ptr->prep_func))(player_ptr);
249         get_mon_num_prep(player_ptr, n_ptr->hook_func, NULL);
250
251         align.sub_align = SUB_ALIGN_NEUTRAL;
252
253         /* Pick some monster types */
254         for (i = 0; i < NUM_NEST_MON_TYPE; i++)
255         {
256                 MONRACE_IDX r_idx = 0;
257                 int attempts = 100;
258                 monster_race *r_ptr = NULL;
259
260                 while (attempts--)
261                 {
262                         /* Get a (hard) monster type */
263                         r_idx = get_mon_num(player_ptr, floor_ptr->dun_level + 11, 0);
264                         r_ptr = &r_info[r_idx];
265
266                         /* Decline incorrect alignment */
267                         if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr)) continue;
268
269                         /* Accept this monster */
270                         break;
271                 }
272
273                 /* Notice failure */
274                 if (!r_idx || !attempts) return FALSE;
275
276                 /* Note the alignment */
277                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
278                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
279
280                 nest_mon_info[i].r_idx = (s16b)r_idx;
281                 nest_mon_info[i].used = FALSE;
282         }
283
284         /* Find and reserve some space in the dungeon.  Get center of room. */
285         if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25)) return FALSE;
286
287         /* Large room */
288         y1 = yval - 4;
289         y2 = yval + 4;
290         x1 = xval - 11;
291         x2 = xval + 11;
292
293         /* Place the floor area */
294         for (y = y1 - 1; y <= y2 + 1; y++)
295         {
296                 for (x = x1 - 1; x <= x2 + 1; x++)
297                 {
298                         g_ptr = &floor_ptr->grid_array[y][x];
299                         place_grid(player_ptr, g_ptr, GB_FLOOR);
300                         g_ptr->info |= (CAVE_ROOM);
301                 }
302         }
303
304         /* Place the outer walls */
305         for (y = y1 - 1; y <= y2 + 1; y++)
306         {
307                 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
308                 place_grid(player_ptr, g_ptr, GB_OUTER);
309                 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
310                 place_grid(player_ptr, g_ptr, GB_OUTER);
311         }
312         for (x = x1 - 1; x <= x2 + 1; x++)
313         {
314                 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
315                 place_grid(player_ptr, g_ptr, GB_OUTER);
316                 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
317                 place_grid(player_ptr, g_ptr, GB_OUTER);
318         }
319
320
321         /* Advance to the center room */
322         y1 = y1 + 2;
323         y2 = y2 - 2;
324         x1 = x1 + 2;
325         x2 = x2 - 2;
326
327         /* The inner walls */
328         for (y = y1 - 1; y <= y2 + 1; y++)
329         {
330                 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
331                 place_grid(player_ptr, g_ptr, GB_INNER);
332                 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
333                 place_grid(player_ptr, g_ptr, GB_INNER);
334         }
335
336         for (x = x1 - 1; x <= x2 + 1; x++)
337         {
338                 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
339                 place_grid(player_ptr, g_ptr, GB_INNER);
340                 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
341                 place_grid(player_ptr, g_ptr, GB_INNER);
342         }
343         for (y = y1; y <= y2; y++)
344         {
345                 for (x = x1; x <= x2; x++)
346                 {
347                         add_cave_info(floor_ptr, y, x, CAVE_ICKY);
348                 }
349         }
350
351         /* Place a secret door */
352         switch (randint1(4))
353         {
354         case 1: place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT); break;
355         case 2: place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT); break;
356         case 3: place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT); break;
357         case 4: place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT); break;
358         }
359
360         msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name,
361             pit_subtype_string(cur_nest_type, TRUE));
362
363         /* Place some monsters */
364         for (y = yval - 2; y <= yval + 2; y++)
365         {
366                 for (x = xval - 9; x <= xval + 9; x++)
367                 {
368                         MONRACE_IDX r_idx;
369
370                         i = randint0(NUM_NEST_MON_TYPE);
371                         r_idx = nest_mon_info[i].r_idx;
372
373                         /* Place that "random" monster (no groups) */
374                         (void)place_monster_aux(player_ptr, 0, y, x, r_idx, 0L);
375
376                         nest_mon_info[i].used = TRUE;
377                 }
378         }
379
380         if (cheat_room)
381         {
382                 ang_sort(player_ptr, nest_mon_info, NULL, NUM_NEST_MON_TYPE, ang_sort_comp_nest_mon_info, ang_sort_swap_nest_mon_info);
383
384                 /* Dump the entries (prevent multi-printing) */
385                 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
386                 {
387                         if (!nest_mon_info[i].used) break;
388                         for (; i < NUM_NEST_MON_TYPE - 1; i++)
389                         {
390                                 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;
391                                 if (!nest_mon_info[i + 1].used) break;
392                         }
393
394                         msg_format_wizard(player_ptr, CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);
395                 }
396         }
397
398         return TRUE;
399 }
400
401
402 /*!
403 * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits
404 * @return なし
405 * @details
406 * A monster pit is a "big" room, with an "inner" room, containing\n
407 * a "collection" of monsters of a given type organized in the room.\n
408 *\n
409 * The inside room in a monster pit appears as shown below, where the\n
410 * actual monsters in each location depend on the type of the pit\n
411 *\n
412 *   XXXXXXXXXXXXXXXXXXXXX\n
413 *   X0000000000000000000X\n
414 *   X0112233455543322110X\n
415 *   X0112233467643322110X\n
416 *   X0112233455543322110X\n
417 *   X0000000000000000000X\n
418 *   XXXXXXXXXXXXXXXXXXXXX\n
419 *\n
420 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
421 * to request 16 "appropriate" monsters, sorting them by level, and using\n
422 * the "even" entries in this sorted list for the contents of the pit.\n
423 *\n
424 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
425 * which is handled by requiring a specific "breath" attack for all of the\n
426 * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n
427 * be present in many of the dragon pits, if they have the proper breath.\n
428 *\n
429 * Note the use of the "get_mon_num_prep()" function, and the special\n
430 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
431 * allocation table" in such a way as to optimize the selection of\n
432 * "appropriate" non-unique monsters for the pit.\n
433 *\n
434 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
435 * the pit will be empty.\n
436 *\n
437 * Note that "monster pits" will never contain "unique" monsters.\n
438 */
439 bool build_type6(player_type *player_ptr, dun_data_type *dd_ptr)
440 {
441         POSITION y, x, y1, x1, y2, x2, xval, yval;
442         int i, j;
443
444         MONRACE_IDX what[16];
445
446         monster_type align;
447
448         grid_type *g_ptr;
449
450         floor_type *floor_ptr = player_ptr->current_floor_ptr;
451         int cur_pit_type = pick_vault_type(floor_ptr, pit_types, d_info[floor_ptr->dungeon_idx].pit);
452         vault_aux_type *n_ptr;
453
454         /* No type available */
455         if (cur_pit_type < 0) return FALSE;
456
457         n_ptr = &pit_types[cur_pit_type];
458
459         /* Process a preparation function if necessary */
460         if (n_ptr->prep_func) (*(n_ptr->prep_func))(player_ptr);
461         get_mon_num_prep(player_ptr, n_ptr->hook_func, NULL);
462
463         align.sub_align = SUB_ALIGN_NEUTRAL;
464
465         /* Pick some monster types */
466         for (i = 0; i < 16; i++)
467         {
468                 MONRACE_IDX r_idx = 0;
469                 int attempts = 100;
470                 monster_race *r_ptr = NULL;
471
472                 while (attempts--)
473                 {
474                         /* Get a (hard) monster type */
475                         r_idx = get_mon_num(player_ptr, floor_ptr->dun_level + 11, 0);
476                         r_ptr = &r_info[r_idx];
477
478                         /* Decline incorrect alignment */
479                         if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr)) continue;
480
481                         /* Accept this monster */
482                         break;
483                 }
484
485                 /* Notice failure */
486                 if (!r_idx || !attempts) return FALSE;
487
488                 /* Note the alignment */
489                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
490                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
491
492                 what[i] = r_idx;
493         }
494
495         /* Find and reserve some space in the dungeon.  Get center of room. */
496         if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25)) return FALSE;
497
498         /* Large room */
499         y1 = yval - 4;
500         y2 = yval + 4;
501         x1 = xval - 11;
502         x2 = xval + 11;
503
504         /* Place the floor area */
505         for (y = y1 - 1; y <= y2 + 1; y++)
506         {
507                 for (x = x1 - 1; x <= x2 + 1; x++)
508                 {
509                         g_ptr = &floor_ptr->grid_array[y][x];
510                         place_grid(player_ptr, g_ptr, GB_FLOOR);
511                         g_ptr->info |= (CAVE_ROOM);
512                 }
513         }
514
515         /* Place the outer walls */
516         for (y = y1 - 1; y <= y2 + 1; y++)
517         {
518                 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
519                 place_grid(player_ptr, g_ptr, GB_OUTER);
520                 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
521                 place_grid(player_ptr, g_ptr, GB_OUTER);
522         }
523         for (x = x1 - 1; x <= x2 + 1; x++)
524         {
525                 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
526                 place_grid(player_ptr, g_ptr, GB_OUTER);
527                 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
528                 place_grid(player_ptr, g_ptr, GB_OUTER);
529         }
530
531         /* Advance to the center room */
532         y1 = y1 + 2;
533         y2 = y2 - 2;
534         x1 = x1 + 2;
535         x2 = x2 - 2;
536
537         /* The inner walls */
538         for (y = y1 - 1; y <= y2 + 1; y++)
539         {
540                 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
541                 place_grid(player_ptr, g_ptr, GB_INNER);
542                 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
543                 place_grid(player_ptr, g_ptr, GB_INNER);
544         }
545         for (x = x1 - 1; x <= x2 + 1; x++)
546         {
547                 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
548                 place_grid(player_ptr, g_ptr, GB_INNER);
549                 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
550                 place_grid(player_ptr, g_ptr, GB_INNER);
551         }
552         for (y = y1; y <= y2; y++)
553         {
554                 for (x = x1; x <= x2; x++)
555                 {
556                         add_cave_info(floor_ptr, y, x, CAVE_ICKY);
557                 }
558         }
559
560         /* Place a secret door */
561         switch (randint1(4))
562         {
563         case 1: place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT); break;
564         case 2: place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT); break;
565         case 3: place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT); break;
566         case 4: place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT); break;
567         }
568
569         /* Sort the entries */
570         for (i = 0; i < 16 - 1; i++)
571         {
572                 /* Sort the entries */
573                 for (j = 0; j < 16 - 1; j++)
574                 {
575                         int i1 = j;
576                         int i2 = j + 1;
577
578                         int p1 = r_info[what[i1]].level;
579                         int p2 = r_info[what[i2]].level;
580
581                         /* Bubble */
582                         if (p1 > p2)
583                         {
584                                 MONRACE_IDX tmp = what[i1];
585                                 what[i1] = what[i2];
586                                 what[i2] = tmp;
587                         }
588                 }
589         }
590
591         msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name,
592             pit_subtype_string(cur_pit_type, FALSE));
593
594         /* Select the entries */
595         for (i = 0; i < 8; i++)
596         {
597                 /* Every other entry */
598                 what[i] = what[i * 2];
599                 msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);
600         }
601
602         /* Top and bottom rows */
603         for (x = xval - 9; x <= xval + 9; x++)
604         {
605                 place_monster_aux(player_ptr, 0, yval - 2, x, what[0], PM_NO_KAGE);
606                 place_monster_aux(player_ptr, 0, yval + 2, x, what[0], PM_NO_KAGE);
607         }
608
609         /* Middle columns */
610         for (y = yval - 1; y <= yval + 1; y++)
611         {
612                 place_monster_aux(player_ptr, 0, y, xval - 9, what[0], PM_NO_KAGE);
613                 place_monster_aux(player_ptr, 0, y, xval + 9, what[0], PM_NO_KAGE);
614
615                 place_monster_aux(player_ptr, 0, y, xval - 8, what[1], PM_NO_KAGE);
616                 place_monster_aux(player_ptr, 0, y, xval + 8, what[1], PM_NO_KAGE);
617
618                 place_monster_aux(player_ptr, 0, y, xval - 7, what[1], PM_NO_KAGE);
619                 place_monster_aux(player_ptr, 0, y, xval + 7, what[1], PM_NO_KAGE);
620
621                 place_monster_aux(player_ptr, 0, y, xval - 6, what[2], PM_NO_KAGE);
622                 place_monster_aux(player_ptr, 0, y, xval + 6, what[2], PM_NO_KAGE);
623
624                 place_monster_aux(player_ptr, 0, y, xval - 5, what[2], PM_NO_KAGE);
625                 place_monster_aux(player_ptr, 0, y, xval + 5, what[2], PM_NO_KAGE);
626
627                 place_monster_aux(player_ptr, 0, y, xval - 4, what[3], PM_NO_KAGE);
628                 place_monster_aux(player_ptr, 0, y, xval + 4, what[3], PM_NO_KAGE);
629
630                 place_monster_aux(player_ptr, 0, y, xval - 3, what[3], PM_NO_KAGE);
631                 place_monster_aux(player_ptr, 0, y, xval + 3, what[3], PM_NO_KAGE);
632
633                 place_monster_aux(player_ptr, 0, y, xval - 2, what[4], PM_NO_KAGE);
634                 place_monster_aux(player_ptr, 0, y, xval + 2, what[4], PM_NO_KAGE);
635         }
636
637         /* Above/Below the center monster */
638         for (x = xval - 1; x <= xval + 1; x++)
639         {
640                 place_monster_aux(player_ptr, 0, yval + 1, x, what[5], PM_NO_KAGE);
641                 place_monster_aux(player_ptr, 0, yval - 1, x, what[5], PM_NO_KAGE);
642         }
643
644         /* Next to the center monster */
645         place_monster_aux(player_ptr, 0, yval, xval + 1, what[6], PM_NO_KAGE);
646         place_monster_aux(player_ptr, 0, yval, xval - 1, what[6], PM_NO_KAGE);
647
648         /* Center monster */
649         place_monster_aux(player_ptr, 0, yval, xval, what[7], PM_NO_KAGE);
650
651         return TRUE;
652 }
653
654 /*
655  * Helper function for "trapped monster pit"
656  */
657 static bool vault_aux_trapped_pit(player_type *player_ptr, MONRACE_IDX r_idx)
658 {
659     /* Unused */
660     (void)player_ptr;
661
662     monster_race *r_ptr = &r_info[r_idx];
663
664         if (!vault_monster_okay(player_ptr, r_idx)) return FALSE;
665
666         /* No wall passing monster */
667         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return FALSE;
668
669         return TRUE;
670 }
671
672
673 /*!
674 * @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits
675 * @return なし
676 * @details
677 * A trapped monster pit is a "big" room with a straight corridor in\n
678 * which wall opening traps are placed, and with two "inner" rooms\n
679 * containing a "collection" of monsters of a given type organized in\n
680 * the room.\n
681 *\n
682 * The trapped monster pit appears as shown below, where the actual\n
683 * monsters in each location depend on the type of the pit\n
684 *\n
685 *  XXXXXXXXXXXXXXXXXXXXXXXXX\n
686 *  X                       X\n
687 *  XXXXXXXXXXXXXXXXXXXXXXX X\n
688 *  XXXXX001123454321100XXX X\n
689 *  XXX0012234567654322100X X\n
690 *  XXXXXXXXXXXXXXXXXXXXXXX X\n
691 *  X           ^           X\n
692 *  X XXXXXXXXXXXXXXXXXXXXXXX\n
693 *  X X0012234567654322100XXX\n
694 *  X XXX001123454321100XXXXX\n
695 *  X XXXXXXXXXXXXXXXXXXXXXXX\n
696 *  X                       X\n
697 *  XXXXXXXXXXXXXXXXXXXXXXXXX\n
698 *\n
699 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
700 * to request 16 "appropriate" monsters, sorting them by level, and using\n
701 * the "even" entries in this sorted list for the contents of the pit.\n
702 *\n
703 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
704 * which is handled by requiring a specific "breath" attack for all of the\n
705 * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n
706 * be present in many of the dragon pits, if they have the proper breath.\n
707 *\n
708 * Note the use of the "get_mon_num_prep()" function, and the special\n
709 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
710 * allocation table" in such a way as to optimize the selection of\n
711 * "appropriate" non-unique monsters for the pit.\n
712 *\n
713 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
714 * the pit will be empty.\n
715 *\n
716 * Note that "monster pits" will never contain "unique" monsters.\n
717 */
718 bool build_type13(player_type *player_ptr, dun_data_type *dd_ptr)
719 {
720         POSITION y, x, y1, x1, y2, x2, xval, yval;
721         int i, j;
722
723         MONRACE_IDX what[16];
724
725         monster_type align;
726
727         grid_type *g_ptr;
728
729         floor_type *floor_ptr = player_ptr->current_floor_ptr;
730         int cur_pit_type = pick_vault_type(floor_ptr, pit_types, d_info[floor_ptr->dungeon_idx].pit);
731         vault_aux_type *n_ptr;
732
733         /* Only in Angband */
734         if (floor_ptr->dungeon_idx != DUNGEON_ANGBAND) return FALSE;
735
736         /* No type available */
737         if (cur_pit_type < 0) return FALSE;
738
739         n_ptr = &pit_types[cur_pit_type];
740
741         /* Process a preparation function if necessary */
742         if (n_ptr->prep_func) (*(n_ptr->prep_func))(player_ptr);
743         get_mon_num_prep(player_ptr, n_ptr->hook_func, vault_aux_trapped_pit);
744
745         align.sub_align = SUB_ALIGN_NEUTRAL;
746
747         /* Pick some monster types */
748         for (i = 0; i < 16; i++)
749         {
750                 MONRACE_IDX r_idx = 0;
751                 int attempts = 100;
752                 monster_race *r_ptr = NULL;
753
754                 while (attempts--)
755                 {
756                         /* Get a (hard) monster type */
757                         r_idx = get_mon_num(player_ptr, floor_ptr->dun_level + 0, 0);
758                         r_ptr = &r_info[r_idx];
759
760                         /* Decline incorrect alignment */
761                         if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr)) continue;
762
763                         /* Accept this monster */
764                         break;
765                 }
766
767                 /* Notice failure */
768                 if (!r_idx || !attempts) return FALSE;
769
770                 /* Note the alignment */
771                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
772                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
773
774                 what[i] = r_idx;
775         }
776
777         /* Find and reserve some space in the dungeon.  Get center of room. */
778         if (!find_space(player_ptr, dd_ptr, &yval, &xval, 13, 25)) return FALSE;
779
780         /* Large room */
781         y1 = yval - 5;
782         y2 = yval + 5;
783         x1 = xval - 11;
784         x2 = xval + 11;
785
786         /* Fill with inner walls */
787         for (y = y1 - 1; y <= y2 + 1; y++)
788         {
789                 for (x = x1 - 1; x <= x2 + 1; x++)
790                 {
791                         g_ptr = &floor_ptr->grid_array[y][x];
792                         place_grid(player_ptr, g_ptr, GB_INNER);
793                         g_ptr->info |= (CAVE_ROOM);
794                 }
795         }
796
797         /* Place the floor area 1 */
798         for (x = x1 + 3; x <= x2 - 3; x++)
799         {
800                 g_ptr = &floor_ptr->grid_array[yval - 2][x];
801                 place_grid(player_ptr, g_ptr, GB_FLOOR);
802                 add_cave_info(floor_ptr, yval - 2, x, CAVE_ICKY);
803
804                 g_ptr = &floor_ptr->grid_array[yval + 2][x];
805                 place_grid(player_ptr, g_ptr, GB_FLOOR);
806                 add_cave_info(floor_ptr, yval + 2, x, CAVE_ICKY);
807         }
808
809         /* Place the floor area 2 */
810         for (x = x1 + 5; x <= x2 - 5; x++)
811         {
812                 g_ptr = &floor_ptr->grid_array[yval - 3][x];
813                 place_grid(player_ptr, g_ptr, GB_FLOOR);
814                 add_cave_info(floor_ptr, yval - 3, x, CAVE_ICKY);
815
816                 g_ptr = &floor_ptr->grid_array[yval + 3][x];
817                 place_grid(player_ptr, g_ptr, GB_FLOOR);
818                 add_cave_info(floor_ptr, yval + 3, x, CAVE_ICKY);
819         }
820
821         /* Corridor */
822         for (x = x1; x <= x2; x++)
823         {
824                 g_ptr = &floor_ptr->grid_array[yval][x];
825                 place_grid(player_ptr, g_ptr, GB_FLOOR);
826                 g_ptr = &floor_ptr->grid_array[y1][x];
827                 place_grid(player_ptr, g_ptr, GB_FLOOR);
828                 g_ptr = &floor_ptr->grid_array[y2][x];
829                 place_grid(player_ptr, g_ptr, GB_FLOOR);
830         }
831
832         /* Place the outer walls */
833         for (y = y1 - 1; y <= y2 + 1; y++)
834         {
835                 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
836                 place_grid(player_ptr, g_ptr, GB_OUTER);
837                 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
838                 place_grid(player_ptr, g_ptr, GB_OUTER);
839         }
840         for (x = x1 - 1; x <= x2 + 1; x++)
841         {
842                 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
843                 place_grid(player_ptr, g_ptr, GB_OUTER);
844                 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
845                 place_grid(player_ptr, g_ptr, GB_OUTER);
846         }
847
848         /* Random corridor */
849         if (one_in_(2))
850         {
851                 for (y = y1; y <= yval; y++)
852                 {
853                         place_bold(player_ptr, y, x2, GB_FLOOR);
854                         place_bold(player_ptr, y, x1 - 1, GB_SOLID);
855                 }
856                 for (y = yval; y <= y2 + 1; y++)
857                 {
858                         place_bold(player_ptr, y, x1, GB_FLOOR);
859                         place_bold(player_ptr, y, x2 + 1, GB_SOLID);
860                 }
861         }
862         else
863         {
864                 for (y = yval; y <= y2 + 1; y++)
865                 {
866                         place_bold(player_ptr, y, x1, GB_FLOOR);
867                         place_bold(player_ptr, y, x2 + 1, GB_SOLID);
868                 }
869                 for (y = y1; y <= yval; y++)
870                 {
871                         place_bold(player_ptr, y, x2, GB_FLOOR);
872                         place_bold(player_ptr, y, x1 - 1, GB_SOLID);
873                 }
874         }
875
876         /* Place the wall open trap */
877         floor_ptr->grid_array[yval][xval].mimic = floor_ptr->grid_array[yval][xval].feat;
878         floor_ptr->grid_array[yval][xval].feat = feat_trap_open;
879
880         /* Sort the entries */
881         for (i = 0; i < 16 - 1; i++)
882         {
883                 /* Sort the entries */
884                 for (j = 0; j < 16 - 1; j++)
885                 {
886                         int i1 = j;
887                         int i2 = j + 1;
888
889                         int p1 = r_info[what[i1]].level;
890                         int p2 = r_info[what[i2]].level;
891
892                         /* Bubble */
893                         if (p1 > p2)
894                         {
895                                 MONRACE_IDX tmp = what[i1];
896                                 what[i1] = what[i2];
897                                 what[i2] = tmp;
898                         }
899                 }
900         }
901
902         msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),
903                 n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
904
905         /* Select the entries */
906         for (i = 0; i < 8; i++)
907         {
908                 /* Every other entry */
909                 what[i] = what[i * 2];
910
911                 if (cheat_hear)
912                 {
913                         msg_print(r_name + r_info[what[i]].name);
914                 }
915         }
916
917         for (i = 0; placing[i][2] >= 0; i++)
918         {
919                 y = yval + placing[i][0];
920                 x = xval + placing[i][1];
921                 place_monster_aux(player_ptr, 0, y, x, what[placing[i][2]], PM_NO_KAGE);
922         }
923
924         return TRUE;
925 }