OSDN Git Service

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