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-flags7.h"
18 #include "monster/monster-info.h"
19 #include "monster/monster-list.h"
20 #include "monster/monster-util.h"
21 #include "room/space-finder.h"
22 #include "system/floor-type-definition.h"
23 #include "util/probability-table.h"
24 #include "util/sort.h"
25 #include "view/display-messages.h"
26 #include "wizard/wizard-messages.h"
30 * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める
31 * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ
32 * @param allow_flag_mask 生成が許されるpit/nestのビット配列
33 * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。
35 static int pick_vault_type(floor_type *floor_ptr, std::vector<nest_pit_type>& l_ptr, BIT_FLAGS16 allow_flag_mask)
37 ProbabilityTable<int> table;
38 for (size_t i = 0; i < l_ptr.size(); i++) {
39 nest_pit_type *n_ptr = &l_ptr.at(i);
41 if (n_ptr->level > floor_ptr->dun_level)
44 if (!(allow_flag_mask & (1UL << i)))
47 table.entry_item(i, n_ptr->chance * MAX_DEPTH / (MIN(floor_ptr->dun_level, MAX_DEPTH - 1) - n_ptr->level + 5));
50 return !table.empty() ? table.pick_one_at_random() : -1;
54 * @brief デバッグ時に生成されたpit/nestの型を出力する処理
55 * @param type pit/nestの型ID
56 * @param nest TRUEならばnest、FALSEならばpit
57 * @return デバッグ表示文字列の参照ポインタ
59 * Hack -- Get the string describing subtype of pit/nest
60 * Determined in prepare function (some pit/nest only)
62 static concptr pit_subtype_string(int type, bool nest)
64 static char inner_buf[256] = "";
69 sprintf(inner_buf, "(%s)", r_info[vault_aux_race].name.c_str());
71 case NEST_TYPE_SYMBOL_GOOD:
72 case NEST_TYPE_SYMBOL_EVIL:
73 sprintf(inner_buf, "(%c)", vault_aux_char);
82 case PIT_TYPE_SYMBOL_GOOD:
83 case PIT_TYPE_SYMBOL_EVIL:
84 sprintf(inner_buf, "(%c)", vault_aux_char);
87 if (vault_aux_dragon_mask4.has_all_of({ RF_ABILITY::BR_ACID, RF_ABILITY::BR_ELEC, RF_ABILITY::BR_FIRE, RF_ABILITY::BR_COLD, RF_ABILITY::BR_POIS })) {
88 strcpy(inner_buf, _("(万色)", "(multi-hued)"));
89 } else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_ACID)) {
90 strcpy(inner_buf, _("(酸)", "(acid)"));
91 }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_ELEC)) {
92 strcpy(inner_buf, _("(稲妻)", "(lightning)"));
93 }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_FIRE)) {
94 strcpy(inner_buf, _("(火炎)", "(fire)"));
95 }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_COLD)) {
96 strcpy(inner_buf, _("(冷気)", "(frost)"));
97 }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_POIS)) {
98 strcpy(inner_buf, _("(毒)", "(poison)"));
100 strcpy(inner_buf, _("(未定義)", "(undefined)"));
109 *! @brief nestのモンスターリストをソートするための関数 /
110 * Comp function for sorting nest monster information
111 * @param u ソート処理対象配列ポインタ
117 static bool ang_sort_comp_nest_mon_info(player_type *player_ptr, vptr u, vptr v, int a, int b)
123 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
124 MONSTER_IDX w1 = nest_mon_info[a].r_idx;
125 MONSTER_IDX w2 = nest_mon_info[b].r_idx;
126 monster_race *r1_ptr = &r_info[w1];
127 monster_race *r2_ptr = &r_info[w2];
128 int z1 = nest_mon_info[a].used;
129 int z2 = nest_mon_info[b].used;
136 if (r1_ptr->level < r2_ptr->level)
138 if (r1_ptr->level > r2_ptr->level)
141 if (r1_ptr->mexp < r2_ptr->mexp)
143 if (r1_ptr->mexp > r2_ptr->mexp)
150 * @brief nestのモンスターリストをスワップするための関数 /
151 * Swap function for sorting nest monster information
152 * @param u スワップ処理対象配列ポインタ
154 * @param a スワップ対象参照ID1
155 * @param b スワップ対象参照ID2
158 static void ang_sort_swap_nest_mon_info(player_type *player_ptr, vptr u, vptr v, int a, int b)
164 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
165 nest_mon_info_type holder = nest_mon_info[a];
166 nest_mon_info[a] = nest_mon_info[b];
167 nest_mon_info[b] = holder;
171 * @brief 生成するNestの情報テーブル
173 std::vector<nest_pit_type> nest_types = {
174 { _("クローン", "clone"), vault_aux_clone, vault_prep_clone, 5, 3 },
175 { _("ゼリー", "jelly"), vault_aux_jelly, NULL, 5, 6 },
176 { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 25, 2 },
177 { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 25, 2 },
178 { _("ミミック", "mimic"), vault_aux_mimic, NULL, 30, 4 },
179 { _("狂気", "lovecraftian"), vault_aux_cthulhu, NULL, 70, 2 },
180 { _("犬小屋", "kennel"), vault_aux_kennel, NULL, 45, 4 },
181 { _("動物園", "animal"), vault_aux_animal, NULL, 35, 5 },
182 { _("教会", "chapel"), vault_aux_chapel_g, NULL, 75, 4 },
183 { _("アンデッド", "undead"), vault_aux_undead, NULL, 75, 5 },
187 * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests
188 * @param player_ptr プレーヤーへの参照ポインタ
191 * A monster nest is a "big" room, with an "inner" room, containing\n
192 * a "collection" of monsters of a given type strewn about the room.\n
194 * The monsters are chosen from a set of 64 randomly selected monster\n
195 * races, to allow the nest creation to fail instead of having "holes".\n
197 * Note the use of the "get_mon_num_prep()" function, and the special\n
198 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
199 * allocation table" in such a way as to optimize the selection of\n
200 * "appropriate" non-unique monsters for the nest.\n
202 * Note that the "get_mon_num()" function may (rarely) fail, in which\n
203 * case the nest will be empty.\n
205 * Note that "monster nests" will never contain "unique" monsters.\n
207 bool build_type5(player_type *player_ptr, dun_data_type *dd_ptr)
209 POSITION y, x, y1, x1, y2, x2, xval, yval;
211 nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
217 floor_type *floor_ptr = player_ptr->current_floor_ptr;
218 int cur_nest_type = pick_vault_type(floor_ptr, nest_types, d_info[floor_ptr->dungeon_idx].nest);
219 nest_pit_type *n_ptr;
221 /* No type available */
222 if (cur_nest_type < 0)
225 n_ptr = &nest_types[cur_nest_type];
227 /* Process a preparation function if necessary */
228 if (n_ptr->prep_func)
229 (*(n_ptr->prep_func))(player_ptr);
230 get_mon_num_prep(player_ptr, n_ptr->hook_func, NULL);
232 align.sub_align = SUB_ALIGN_NEUTRAL;
234 /* Pick some monster types */
235 for (i = 0; i < NUM_NEST_MON_TYPE; i++) {
236 MONRACE_IDX r_idx = 0;
238 monster_race *r_ptr = NULL;
241 /* Get a (hard) monster type */
242 r_idx = get_mon_num(player_ptr, 0, floor_ptr->dun_level + 11, 0);
243 r_ptr = &r_info[r_idx];
245 /* Decline incorrect alignment */
246 if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr))
249 /* Accept this monster */
254 if (!r_idx || !attempts)
257 /* Note the alignment */
258 if (r_ptr->flags3 & RF3_EVIL)
259 align.sub_align |= SUB_ALIGN_EVIL;
260 if (r_ptr->flags3 & RF3_GOOD)
261 align.sub_align |= SUB_ALIGN_GOOD;
263 nest_mon_info[i].r_idx = (s16b)r_idx;
264 nest_mon_info[i].used = FALSE;
267 /* Find and reserve some space in the dungeon. Get center of room. */
268 if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25))
277 /* Place the floor area */
278 for (y = y1 - 1; y <= y2 + 1; y++) {
279 for (x = x1 - 1; x <= x2 + 1; x++) {
280 g_ptr = &floor_ptr->grid_array[y][x];
281 place_grid(player_ptr, g_ptr, GB_FLOOR);
282 g_ptr->info |= (CAVE_ROOM);
286 /* Place the outer walls */
287 for (y = y1 - 1; y <= y2 + 1; y++) {
288 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
289 place_grid(player_ptr, g_ptr, GB_OUTER);
290 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
291 place_grid(player_ptr, g_ptr, GB_OUTER);
293 for (x = x1 - 1; x <= x2 + 1; x++) {
294 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
295 place_grid(player_ptr, g_ptr, GB_OUTER);
296 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
297 place_grid(player_ptr, g_ptr, GB_OUTER);
300 /* Advance to the center room */
306 /* The inner walls */
307 for (y = y1 - 1; y <= y2 + 1; y++) {
308 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
309 place_grid(player_ptr, g_ptr, GB_INNER);
310 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
311 place_grid(player_ptr, g_ptr, GB_INNER);
314 for (x = x1 - 1; x <= x2 + 1; x++) {
315 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
316 place_grid(player_ptr, g_ptr, GB_INNER);
317 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
318 place_grid(player_ptr, g_ptr, GB_INNER);
320 for (y = y1; y <= y2; y++) {
321 for (x = x1; x <= x2; x++) {
322 add_cave_info(floor_ptr, y, x, CAVE_ICKY);
326 /* Place a secret door */
327 switch (randint1(4)) {
329 place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
332 place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
335 place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
338 place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
343 player_ptr, CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
345 /* Place some monsters */
346 for (y = yval - 2; y <= yval + 2; y++) {
347 for (x = xval - 9; x <= xval + 9; x++) {
350 i = randint0(NUM_NEST_MON_TYPE);
351 r_idx = nest_mon_info[i].r_idx;
353 /* Place that "random" monster (no groups) */
354 (void)place_monster_aux(player_ptr, 0, y, x, r_idx, 0L);
356 nest_mon_info[i].used = TRUE;
361 ang_sort(player_ptr, nest_mon_info, NULL, NUM_NEST_MON_TYPE, ang_sort_comp_nest_mon_info, ang_sort_swap_nest_mon_info);
363 /* Dump the entries (prevent multi-printing) */
364 for (i = 0; i < NUM_NEST_MON_TYPE; i++) {
365 if (!nest_mon_info[i].used)
367 for (; i < NUM_NEST_MON_TYPE - 1; i++) {
368 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx)
370 if (!nest_mon_info[i + 1].used)
374 msg_format_wizard(player_ptr, CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_info[nest_mon_info[i].r_idx].name.c_str());
382 * @brief 生成するPitの情報テーブル
384 std::vector<nest_pit_type> pit_types = {
385 { _("オーク", "orc"), vault_aux_orc, NULL, 5, 6 },
386 { _("トロル", "troll"), vault_aux_troll, NULL, 20, 6 },
387 { _("巨人", "giant"), vault_aux_giant, NULL, 50, 6 },
388 { _("狂気", "lovecraftian"), vault_aux_cthulhu, NULL, 80, 2 },
389 { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 70, 1 },
390 { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 70, 1 },
391 { _("教会", "chapel"), vault_aux_chapel_g, NULL, 65, 2 },
392 { _("ドラゴン", "dragon"), vault_aux_dragon, vault_prep_dragon, 70, 6 },
393 { _("デーモン", "demon"), vault_aux_demon, NULL, 80, 6 },
394 { _("ダークエルフ", "dark elf"), vault_aux_dark_elf, NULL, 45, 4 },
398 * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits
401 * A monster pit is a "big" room, with an "inner" room, containing\n
402 * a "collection" of monsters of a given type organized in the room.\n
404 * The inside room in a monster pit appears as shown below, where the\n
405 * actual monsters in each location depend on the type of the pit\n
407 * XXXXXXXXXXXXXXXXXXXXX\n
408 * X0000000000000000000X\n
409 * X0112233455543322110X\n
410 * X0112233467643322110X\n
411 * X0112233455543322110X\n
412 * X0000000000000000000X\n
413 * XXXXXXXXXXXXXXXXXXXXX\n
415 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
416 * to request 16 "appropriate" monsters, sorting them by level, and using\n
417 * the "even" entries in this sorted list for the contents of the pit.\n
419 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
420 * which is handled by requiring a specific "breath" attack for all of the\n
421 * dragons. This may include "multi-hued" breath. Note that "wyrms" may\n
422 * be present in many of the dragon pits, if they have the proper breath.\n
424 * Note the use of the "get_mon_num_prep()" function, and the special\n
425 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
426 * allocation table" in such a way as to optimize the selection of\n
427 * "appropriate" non-unique monsters for the pit.\n
429 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
430 * the pit will be empty.\n
432 * Note that "monster pits" will never contain "unique" monsters.\n
434 bool build_type6(player_type *player_ptr, dun_data_type *dd_ptr)
436 POSITION y, x, y1, x1, y2, x2, xval, yval;
439 MONRACE_IDX what[16];
445 floor_type *floor_ptr = player_ptr->current_floor_ptr;
446 int cur_pit_type = pick_vault_type(floor_ptr, pit_types, d_info[floor_ptr->dungeon_idx].pit);
447 nest_pit_type *n_ptr;
449 /* No type available */
450 if (cur_pit_type < 0)
453 n_ptr = &pit_types[cur_pit_type];
455 /* Process a preparation function if necessary */
456 if (n_ptr->prep_func)
457 (*(n_ptr->prep_func))(player_ptr);
458 get_mon_num_prep(player_ptr, n_ptr->hook_func, NULL);
460 align.sub_align = SUB_ALIGN_NEUTRAL;
462 /* Pick some monster types */
463 for (i = 0; i < 16; i++) {
464 MONRACE_IDX r_idx = 0;
466 monster_race *r_ptr = NULL;
469 /* Get a (hard) monster type */
470 r_idx = get_mon_num(player_ptr, 0, floor_ptr->dun_level + 11, 0);
471 r_ptr = &r_info[r_idx];
473 /* Decline incorrect alignment */
474 if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr))
477 /* Accept this monster */
482 if (!r_idx || !attempts)
485 /* Note the alignment */
486 if (r_ptr->flags3 & RF3_EVIL)
487 align.sub_align |= SUB_ALIGN_EVIL;
488 if (r_ptr->flags3 & RF3_GOOD)
489 align.sub_align |= SUB_ALIGN_GOOD;
494 /* Find and reserve some space in the dungeon. Get center of room. */
495 if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25))
504 /* Place the floor area */
505 for (y = y1 - 1; y <= y2 + 1; y++) {
506 for (x = x1 - 1; x <= x2 + 1; x++) {
507 g_ptr = &floor_ptr->grid_array[y][x];
508 place_grid(player_ptr, g_ptr, GB_FLOOR);
509 g_ptr->info |= (CAVE_ROOM);
513 /* Place the outer walls */
514 for (y = y1 - 1; y <= y2 + 1; y++) {
515 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
516 place_grid(player_ptr, g_ptr, GB_OUTER);
517 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
518 place_grid(player_ptr, g_ptr, GB_OUTER);
520 for (x = x1 - 1; x <= x2 + 1; x++) {
521 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
522 place_grid(player_ptr, g_ptr, GB_OUTER);
523 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
524 place_grid(player_ptr, g_ptr, GB_OUTER);
527 /* Advance to the center room */
533 /* The inner walls */
534 for (y = y1 - 1; y <= y2 + 1; y++) {
535 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
536 place_grid(player_ptr, g_ptr, GB_INNER);
537 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
538 place_grid(player_ptr, g_ptr, GB_INNER);
540 for (x = x1 - 1; x <= x2 + 1; x++) {
541 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
542 place_grid(player_ptr, g_ptr, GB_INNER);
543 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
544 place_grid(player_ptr, g_ptr, GB_INNER);
546 for (y = y1; y <= y2; y++) {
547 for (x = x1; x <= x2; x++) {
548 add_cave_info(floor_ptr, y, x, CAVE_ICKY);
552 /* Place a secret door */
553 switch (randint1(4)) {
555 place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
558 place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
561 place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
564 place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
568 /* Sort the entries */
569 for (i = 0; i < 16 - 1; i++) {
570 /* Sort the entries */
571 for (j = 0; j < 16 - 1; j++) {
575 int p1 = r_info[what[i1]].level;
576 int p2 = r_info[what[i2]].level;
580 MONRACE_IDX tmp = what[i1];
588 player_ptr, CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
590 /* Select the entries */
591 for (i = 0; i < 8; i++) {
592 /* Every other entry */
593 what[i] = what[i * 2];
594 msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_info[what[i]].name.c_str());
597 /* Top and bottom rows */
598 for (x = xval - 9; x <= xval + 9; x++) {
599 place_monster_aux(player_ptr, 0, yval - 2, x, what[0], PM_NO_KAGE);
600 place_monster_aux(player_ptr, 0, yval + 2, x, what[0], PM_NO_KAGE);
604 for (y = yval - 1; y <= yval + 1; y++) {
605 place_monster_aux(player_ptr, 0, y, xval - 9, what[0], PM_NO_KAGE);
606 place_monster_aux(player_ptr, 0, y, xval + 9, what[0], PM_NO_KAGE);
608 place_monster_aux(player_ptr, 0, y, xval - 8, what[1], PM_NO_KAGE);
609 place_monster_aux(player_ptr, 0, y, xval + 8, what[1], PM_NO_KAGE);
611 place_monster_aux(player_ptr, 0, y, xval - 7, what[1], PM_NO_KAGE);
612 place_monster_aux(player_ptr, 0, y, xval + 7, what[1], PM_NO_KAGE);
614 place_monster_aux(player_ptr, 0, y, xval - 6, what[2], PM_NO_KAGE);
615 place_monster_aux(player_ptr, 0, y, xval + 6, what[2], PM_NO_KAGE);
617 place_monster_aux(player_ptr, 0, y, xval - 5, what[2], PM_NO_KAGE);
618 place_monster_aux(player_ptr, 0, y, xval + 5, what[2], PM_NO_KAGE);
620 place_monster_aux(player_ptr, 0, y, xval - 4, what[3], PM_NO_KAGE);
621 place_monster_aux(player_ptr, 0, y, xval + 4, what[3], PM_NO_KAGE);
623 place_monster_aux(player_ptr, 0, y, xval - 3, what[3], PM_NO_KAGE);
624 place_monster_aux(player_ptr, 0, y, xval + 3, what[3], PM_NO_KAGE);
626 place_monster_aux(player_ptr, 0, y, xval - 2, what[4], PM_NO_KAGE);
627 place_monster_aux(player_ptr, 0, y, xval + 2, what[4], PM_NO_KAGE);
630 /* Above/Below the center monster */
631 for (x = xval - 1; x <= xval + 1; x++) {
632 place_monster_aux(player_ptr, 0, yval + 1, x, what[5], PM_NO_KAGE);
633 place_monster_aux(player_ptr, 0, yval - 1, x, what[5], PM_NO_KAGE);
636 /* Next to the center monster */
637 place_monster_aux(player_ptr, 0, yval, xval + 1, what[6], PM_NO_KAGE);
638 place_monster_aux(player_ptr, 0, yval, xval - 1, what[6], PM_NO_KAGE);
641 place_monster_aux(player_ptr, 0, yval, xval, what[7], PM_NO_KAGE);
648 * @brief 開門トラップのモンスター配置テーブル
650 * 中央からの相対座標(X,Y)、モンスターの強さ
652 const int place_table_trapped_pit[TRAPPED_PIT_MONSTER_PLACE_MAX][3] = {
653 { -2, -9, 0 }, { -2, -8, 0 }, { -3, -7, 0 }, { -3, -6, 0 }, { +2, -9, 0 }, { +2, -8, 0 }, { +3, -7, 0 }, { +3, -6, 0 },
654 { -2, +9, 0 }, { -2, +8, 0 }, { -3, +7, 0 }, { -3, +6, 0 }, { +2, +9, 0 }, { +2, +8, 0 }, { +3, +7, 0 }, { +3, +6, 0 },
655 { -2, -7, 1 }, { -3, -5, 1 }, { -3, -4, 1 }, { -2, +7, 1 }, { -3, +5, 1 }, { -3, +4, 1 },
656 { +2, -7, 1 }, { +3, -5, 1 }, { +3, -4, 1 }, { +2, +7, 1 }, { +3, +5, 1 }, { +3, +4, 1 },
657 { -2, -6, 2 }, { -2, -5, 2 }, { -3, -3, 2 }, { -2, +6, 2 }, { -2, +5, 2 }, { -3, +3, 2 },
658 { +2, -6, 2 }, { +2, -5, 2 }, { +3, -3, 2 }, { +2, +6, 2 }, { +2, +5, 2 }, { +3, +3, 2 },
659 { -2, -4, 3 }, { -3, -2, 3 }, { -2, +4, 3 }, { -3, +2, 3 },
660 { +2, -4, 3 }, { +3, -2, 3 }, { +2, +4, 3 }, { +3, +2, 3 },
661 { -2, -3, 4 }, { -3, -1, 4 }, { +2, -3, 4 }, { +3, -1, 4 },
662 { -2, +3, 4 }, { -3, +1, 4 }, { +2, +3, 4 }, { +3, +1, 4 },
663 { -2, -2, 5 }, { -3, 0, 5 }, { -2, +2, 5 }, { +2, -2, 5 }, { +3, 0, 5 }, { +2, +2, 5 },
664 { -2, -1, 6 }, { -2, +1, 6 }, { +2, -1, 6 }, { +2, +1, 6 },
665 { -2, 0, 7 }, { +2, 0, 7 },
670 * @brief 開門トラップに配置するモンスターの条件フィルタ
672 * 穴を掘るモンスター、壁を抜けるモンスターは却下
674 static bool vault_aux_trapped_pit(player_type *player_ptr, MONRACE_IDX r_idx)
679 monster_race *r_ptr = &r_info[r_idx];
681 if (!vault_monster_okay(player_ptr, r_idx))
684 /* No wall passing monster */
685 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL))
692 * @brief タイプ13の部屋…開門トラップpitの生成 / Type 13 -- Trapped monster pits
695 * A trapped monster pit is a "big" room with a straight corridor in\n
696 * which wall opening traps are placed, and with two "inner" rooms\n
697 * containing a "collection" of monsters of a given type organized in\n
700 * The trapped monster pit appears as shown below, where the actual\n
701 * monsters in each location depend on the type of the pit\n
703 * XXXXXXXXXXXXXXXXXXXXXXXXX\n
705 * XXXXXXXXXXXXXXXXXXXXXXX X\n
706 * XXXXX001123454321100XXX X\n
707 * XXX0012234567654322100X X\n
708 * XXXXXXXXXXXXXXXXXXXXXXX X\n
710 * X XXXXXXXXXXXXXXXXXXXXXXX\n
711 * X X0012234567654322100XXX\n
712 * X XXX001123454321100XXXXX\n
713 * X XXXXXXXXXXXXXXXXXXXXXXX\n
715 * XXXXXXXXXXXXXXXXXXXXXXXXX\n
717 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
718 * to request 16 "appropriate" monsters, sorting them by level, and using\n
719 * the "even" entries in this sorted list for the contents of the pit.\n
721 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
722 * which is handled by requiring a specific "breath" attack for all of the\n
723 * dragons. This may include "multi-hued" breath. Note that "wyrms" may\n
724 * be present in many of the dragon pits, if they have the proper breath.\n
726 * Note the use of the "get_mon_num_prep()" function, and the special\n
727 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
728 * allocation table" in such a way as to optimize the selection of\n
729 * "appropriate" non-unique monsters for the pit.\n
731 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
732 * the pit will be empty.\n
734 * Note that "monster pits" will never contain "unique" monsters.\n
736 bool build_type13(player_type *player_ptr, dun_data_type *dd_ptr)
738 POSITION y, x, y1, x1, y2, x2, xval, yval;
741 MONRACE_IDX what[16];
747 floor_type *floor_ptr = player_ptr->current_floor_ptr;
748 int cur_pit_type = pick_vault_type(floor_ptr, pit_types, d_info[floor_ptr->dungeon_idx].pit);
749 nest_pit_type *n_ptr;
751 /* Only in Angband */
752 if (floor_ptr->dungeon_idx != DUNGEON_ANGBAND)
755 /* No type available */
756 if (cur_pit_type < 0)
759 n_ptr = &pit_types[cur_pit_type];
761 /* Process a preparation function if necessary */
762 if (n_ptr->prep_func)
763 (*(n_ptr->prep_func))(player_ptr);
764 get_mon_num_prep(player_ptr, n_ptr->hook_func, vault_aux_trapped_pit);
766 align.sub_align = SUB_ALIGN_NEUTRAL;
768 /* Pick some monster types */
769 for (i = 0; i < 16; i++) {
770 MONRACE_IDX r_idx = 0;
772 monster_race *r_ptr = NULL;
775 /* Get a (hard) monster type */
776 r_idx = get_mon_num(player_ptr, 0, floor_ptr->dun_level + 0, 0);
777 r_ptr = &r_info[r_idx];
779 /* Decline incorrect alignment */
780 if (monster_has_hostile_align(player_ptr, &align, 0, 0, r_ptr))
783 /* Accept this monster */
788 if (!r_idx || !attempts)
791 /* Note the alignment */
792 if (r_ptr->flags3 & RF3_EVIL)
793 align.sub_align |= SUB_ALIGN_EVIL;
794 if (r_ptr->flags3 & RF3_GOOD)
795 align.sub_align |= SUB_ALIGN_GOOD;
800 /* Find and reserve some space in the dungeon. Get center of room. */
801 if (!find_space(player_ptr, dd_ptr, &yval, &xval, 13, 25))
810 /* Fill with inner walls */
811 for (y = y1 - 1; y <= y2 + 1; y++) {
812 for (x = x1 - 1; x <= x2 + 1; x++) {
813 g_ptr = &floor_ptr->grid_array[y][x];
814 place_grid(player_ptr, g_ptr, GB_INNER);
815 g_ptr->info |= (CAVE_ROOM);
819 /* Place the floor area 1 */
820 for (x = x1 + 3; x <= x2 - 3; x++) {
821 g_ptr = &floor_ptr->grid_array[yval - 2][x];
822 place_grid(player_ptr, g_ptr, GB_FLOOR);
823 add_cave_info(floor_ptr, yval - 2, x, CAVE_ICKY);
825 g_ptr = &floor_ptr->grid_array[yval + 2][x];
826 place_grid(player_ptr, g_ptr, GB_FLOOR);
827 add_cave_info(floor_ptr, yval + 2, x, CAVE_ICKY);
830 /* Place the floor area 2 */
831 for (x = x1 + 5; x <= x2 - 5; x++) {
832 g_ptr = &floor_ptr->grid_array[yval - 3][x];
833 place_grid(player_ptr, g_ptr, GB_FLOOR);
834 add_cave_info(floor_ptr, yval - 3, x, CAVE_ICKY);
836 g_ptr = &floor_ptr->grid_array[yval + 3][x];
837 place_grid(player_ptr, g_ptr, GB_FLOOR);
838 add_cave_info(floor_ptr, yval + 3, x, CAVE_ICKY);
842 for (x = x1; x <= x2; x++) {
843 g_ptr = &floor_ptr->grid_array[yval][x];
844 place_grid(player_ptr, g_ptr, GB_FLOOR);
845 g_ptr = &floor_ptr->grid_array[y1][x];
846 place_grid(player_ptr, g_ptr, GB_FLOOR);
847 g_ptr = &floor_ptr->grid_array[y2][x];
848 place_grid(player_ptr, g_ptr, GB_FLOOR);
851 /* Place the outer walls */
852 for (y = y1 - 1; y <= y2 + 1; y++) {
853 g_ptr = &floor_ptr->grid_array[y][x1 - 1];
854 place_grid(player_ptr, g_ptr, GB_OUTER);
855 g_ptr = &floor_ptr->grid_array[y][x2 + 1];
856 place_grid(player_ptr, g_ptr, GB_OUTER);
858 for (x = x1 - 1; x <= x2 + 1; x++) {
859 g_ptr = &floor_ptr->grid_array[y1 - 1][x];
860 place_grid(player_ptr, g_ptr, GB_OUTER);
861 g_ptr = &floor_ptr->grid_array[y2 + 1][x];
862 place_grid(player_ptr, g_ptr, GB_OUTER);
865 /* Random corridor */
867 for (y = y1; y <= yval; y++) {
868 place_bold(player_ptr, y, x2, GB_FLOOR);
869 place_bold(player_ptr, y, x1 - 1, GB_SOLID);
871 for (y = yval; y <= y2 + 1; y++) {
872 place_bold(player_ptr, y, x1, GB_FLOOR);
873 place_bold(player_ptr, y, x2 + 1, GB_SOLID);
876 for (y = yval; y <= y2 + 1; y++) {
877 place_bold(player_ptr, y, x1, GB_FLOOR);
878 place_bold(player_ptr, y, x2 + 1, GB_SOLID);
880 for (y = y1; y <= yval; y++) {
881 place_bold(player_ptr, y, x2, GB_FLOOR);
882 place_bold(player_ptr, y, x1 - 1, GB_SOLID);
886 /* Place the wall open trap */
887 floor_ptr->grid_array[yval][xval].mimic = floor_ptr->grid_array[yval][xval].feat;
888 floor_ptr->grid_array[yval][xval].feat = feat_trap_open;
890 /* Sort the entries */
891 for (i = 0; i < 16 - 1; i++) {
892 /* Sort the entries */
893 for (j = 0; j < 16 - 1; j++) {
897 int p1 = r_info[what[i1]].level;
898 int p2 = r_info[what[i2]].level;
902 MONRACE_IDX tmp = what[i1];
910 player_ptr, CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
912 /* Select the entries */
913 for (i = 0; i < 8; i++) {
914 /* Every other entry */
915 what[i] = what[i * 2];
918 msg_print(r_info[what[i]].name.c_str());
922 for (i = 0; place_table_trapped_pit[i][2] >= 0; i++) {
923 y = yval + place_table_trapped_pit[i][0];
924 x = xval + place_table_trapped_pit[i][1];
925 place_monster_aux(player_ptr, 0, y, x, what[place_table_trapped_pit[i][2]], PM_NO_KAGE);