OSDN Git Service

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