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"
7 #include "grid/feature.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"
31 * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める
32 * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ
33 * @param allow_flag_mask 生成が許されるpit/nestのビット配列
34 * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。
36 static int pick_vault_type(floor_type *floor_ptr, std::vector<nest_pit_type>& l_ptr, BIT_FLAGS16 allow_flag_mask)
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);
42 if (n_ptr->level > floor_ptr->dun_level)
45 if (!(allow_flag_mask & (1UL << i)))
48 table.entry_item(i, n_ptr->chance * MAX_DEPTH / (MIN(floor_ptr->dun_level, MAX_DEPTH - 1) - n_ptr->level + 5));
51 return !table.empty() ? table.pick_one_at_random() : -1;
55 * @brief デバッグ時に生成されたpit/nestの型を出力する処理
56 * @param type pit/nestの型ID
57 * @param nest TRUEならばnest、FALSEならばpit
58 * @return デバッグ表示文字列の参照ポインタ
60 * Hack -- Get the string describing subtype of pit/nest
61 * Determined in prepare function (some pit/nest only)
63 static concptr pit_subtype_string(int type, bool nest)
65 static char inner_buf[256] = "";
70 sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
72 case NEST_TYPE_SYMBOL_GOOD:
73 case NEST_TYPE_SYMBOL_EVIL:
74 sprintf(inner_buf, "(%c)", vault_aux_char);
83 case PIT_TYPE_SYMBOL_GOOD:
84 case PIT_TYPE_SYMBOL_EVIL:
85 sprintf(inner_buf, "(%c)", vault_aux_char);
88 switch (vault_aux_dragon_mask4) {
90 strcpy(inner_buf, _("(酸)", "(acid)"));
93 strcpy(inner_buf, _("(稲妻)", "(lightning)"));
96 strcpy(inner_buf, _("(火炎)", "(fire)"));
99 strcpy(inner_buf, _("(冷気)", "(frost)"));
102 strcpy(inner_buf, _("(毒)", "(poison)"));
104 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
105 strcpy(inner_buf, _("(万色)", "(multi-hued)"));
108 strcpy(inner_buf, _("(未定義)", "(undefined)"));
118 *! @brief nestのモンスターリストをソートするための関数 /
119 * Comp function for sorting nest monster information
120 * @param u ソート処理対象配列ポインタ
126 static bool ang_sort_comp_nest_mon_info(player_type *player_ptr, vptr u, vptr v, int a, int b)
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;
145 if (r1_ptr->level < r2_ptr->level)
147 if (r1_ptr->level > r2_ptr->level)
150 if (r1_ptr->mexp < r2_ptr->mexp)
152 if (r1_ptr->mexp > r2_ptr->mexp)
159 * @brief nestのモンスターリストをスワップするための関数 /
160 * Swap function for sorting nest monster information
161 * @param u スワップ処理対象配列ポインタ
163 * @param a スワップ対象参照ID1
164 * @param b スワップ対象参照ID2
167 static void ang_sort_swap_nest_mon_info(player_type *player_ptr, vptr u, vptr v, int a, int b)
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;
180 * @brief 生成するNestの情報テーブル
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 },
196 * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests
197 * @param player_ptr プレーヤーへの参照ポインタ
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
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
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
211 * Note that the "get_mon_num()" function may (rarely) fail, in which\n
212 * case the nest will be empty.\n
214 * Note that "monster nests" will never contain "unique" monsters.\n
216 bool build_type5(player_type *player_ptr, dun_data_type *dd_ptr)
218 POSITION y, x, y1, x1, y2, x2, xval, yval;
220 nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
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;
230 /* No type available */
231 if (cur_nest_type < 0)
234 n_ptr = &nest_types[cur_nest_type];
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);
241 align.sub_align = SUB_ALIGN_NEUTRAL;
243 /* Pick some monster types */
244 for (i = 0; i < NUM_NEST_MON_TYPE; i++) {
245 MONRACE_IDX r_idx = 0;
247 monster_race *r_ptr = NULL;
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];
254 /* Decline incorrect alignment */
255 if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr))
258 /* Accept this monster */
263 if (!r_idx || !attempts)
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;
272 nest_mon_info[i].r_idx = (s16b)r_idx;
273 nest_mon_info[i].used = FALSE;
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))
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);
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);
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);
309 /* Advance to the center room */
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);
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);
329 for (y = y1; y <= y2; y++) {
330 for (x = x1; x <= x2; x++) {
331 add_cave_info(floor_ptr, y, x, CAVE_ICKY);
335 /* Place a secret door */
336 switch (randint1(4)) {
338 place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
341 place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
344 place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
347 place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
352 player_ptr, CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
354 /* Place some monsters */
355 for (y = yval - 2; y <= yval + 2; y++) {
356 for (x = xval - 9; x <= xval + 9; x++) {
359 i = randint0(NUM_NEST_MON_TYPE);
360 r_idx = nest_mon_info[i].r_idx;
362 /* Place that "random" monster (no groups) */
363 (void)place_monster_aux(player_ptr, 0, y, x, r_idx, 0L);
365 nest_mon_info[i].used = TRUE;
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);
372 /* Dump the entries (prevent multi-printing) */
373 for (i = 0; i < NUM_NEST_MON_TYPE; i++) {
374 if (!nest_mon_info[i].used)
376 for (; i < NUM_NEST_MON_TYPE - 1; i++) {
377 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx)
379 if (!nest_mon_info[i + 1].used)
383 msg_format_wizard(player_ptr, CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);
391 * @brief 生成するPitの情報テーブル
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 },
407 * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits
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
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
416 * XXXXXXXXXXXXXXXXXXXXX\n
417 * X0000000000000000000X\n
418 * X0112233455543322110X\n
419 * X0112233467643322110X\n
420 * X0112233455543322110X\n
421 * X0000000000000000000X\n
422 * XXXXXXXXXXXXXXXXXXXXX\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
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
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
438 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
439 * the pit will be empty.\n
441 * Note that "monster pits" will never contain "unique" monsters.\n
443 bool build_type6(player_type *player_ptr, dun_data_type *dd_ptr)
445 POSITION y, x, y1, x1, y2, x2, xval, yval;
448 MONRACE_IDX what[16];
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;
458 /* No type available */
459 if (cur_pit_type < 0)
462 n_ptr = &pit_types[cur_pit_type];
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);
469 align.sub_align = SUB_ALIGN_NEUTRAL;
471 /* Pick some monster types */
472 for (i = 0; i < 16; i++) {
473 MONRACE_IDX r_idx = 0;
475 monster_race *r_ptr = NULL;
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];
482 /* Decline incorrect alignment */
483 if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr))
486 /* Accept this monster */
491 if (!r_idx || !attempts)
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;
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))
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);
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);
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);
536 /* Advance to the center room */
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);
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);
555 for (y = y1; y <= y2; y++) {
556 for (x = x1; x <= x2; x++) {
557 add_cave_info(floor_ptr, y, x, CAVE_ICKY);
561 /* Place a secret door */
562 switch (randint1(4)) {
564 place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
567 place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
570 place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
573 place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
577 /* Sort the entries */
578 for (i = 0; i < 16 - 1; i++) {
579 /* Sort the entries */
580 for (j = 0; j < 16 - 1; j++) {
584 int p1 = r_info[what[i1]].level;
585 int p2 = r_info[what[i2]].level;
589 MONRACE_IDX tmp = what[i1];
597 player_ptr, CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
650 place_monster_aux(player_ptr, 0, yval, xval, what[7], PM_NO_KAGE);
657 * @brief 開門トラップのモンスター配置テーブル
659 * 中央からの相対座標(X,Y)、モンスターの強さ
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 },
679 * @brief 開門トラップに配置するモンスターの条件フィルタ
681 * 穴を掘るモンスター、壁を抜けるモンスターは却下
683 static bool vault_aux_trapped_pit(player_type *player_ptr, MONRACE_IDX r_idx)
688 monster_race *r_ptr = &r_info[r_idx];
690 if (!vault_monster_okay(player_ptr, r_idx))
693 /* No wall passing monster */
694 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL))
701 * @brief タイプ13の部屋…開門トラップpitの生成 / Type 13 -- Trapped monster pits
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
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
712 * XXXXXXXXXXXXXXXXXXXXXXXXX\n
714 * XXXXXXXXXXXXXXXXXXXXXXX X\n
715 * XXXXX001123454321100XXX X\n
716 * XXX0012234567654322100X X\n
717 * XXXXXXXXXXXXXXXXXXXXXXX X\n
719 * X XXXXXXXXXXXXXXXXXXXXXXX\n
720 * X X0012234567654322100XXX\n
721 * X XXX001123454321100XXXXX\n
722 * X XXXXXXXXXXXXXXXXXXXXXXX\n
724 * XXXXXXXXXXXXXXXXXXXXXXXXX\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
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
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
740 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
741 * the pit will be empty.\n
743 * Note that "monster pits" will never contain "unique" monsters.\n
745 bool build_type13(player_type *player_ptr, dun_data_type *dd_ptr)
747 POSITION y, x, y1, x1, y2, x2, xval, yval;
750 MONRACE_IDX what[16];
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;
760 /* Only in Angband */
761 if (floor_ptr->dungeon_idx != DUNGEON_ANGBAND)
764 /* No type available */
765 if (cur_pit_type < 0)
768 n_ptr = &pit_types[cur_pit_type];
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);
775 align.sub_align = SUB_ALIGN_NEUTRAL;
777 /* Pick some monster types */
778 for (i = 0; i < 16; i++) {
779 MONRACE_IDX r_idx = 0;
781 monster_race *r_ptr = NULL;
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];
788 /* Decline incorrect alignment */
789 if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr))
792 /* Accept this monster */
797 if (!r_idx || !attempts)
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;
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))
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);
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);
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);
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);
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);
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);
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);
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);
874 /* Random corridor */
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);
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);
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);
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);
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;
899 /* Sort the entries */
900 for (i = 0; i < 16 - 1; i++) {
901 /* Sort the entries */
902 for (j = 0; j < 16 - 1; j++) {
906 int p1 = r_info[what[i1]].level;
907 int p2 = r_info[what[i2]].level;
911 MONRACE_IDX tmp = what[i1];
919 player_ptr, CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
921 /* Select the entries */
922 for (i = 0; i < 8; i++) {
923 /* Every other entry */
924 what[i] = what[i * 2];
927 msg_print(r_name + r_info[what[i]].name);
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);