OSDN Git Service

[Refactor] #37353 コメント整理 / Refactor comments.
[hengbandforosx/hengbandosx.git] / src / rooms-pitnest.c
1 #include "angband.h"\r
2 #include "grid.h"\r
3 #include "generate.h"\r
4 #include "rooms.h"\r
5 #include "rooms-pitnest.h"\r
6 #include "monster-hook.h"\r
7 \r
8 \r
9 \r
10 #define NUM_NEST_MON_TYPE 64 /*!<nestの種別数 */\r
11 \r
12 /*! pit/nest型情報のtypedef */\r
13 typedef struct vault_aux_type vault_aux_type;\r
14 \r
15 /*! pit/nest型情報の構造体定義 */\r
16 struct vault_aux_type\r
17 {\r
18         cptr name;\r
19         bool(*hook_func)(MONRACE_IDX r_idx);\r
20         void(*prep_func)(void);\r
21         DEPTH level;\r
22         int chance;\r
23 };\r
24 \r
25 /*! nestのID定義 /  Nest types code */\r
26 #define NEST_TYPE_CLONE        0\r
27 #define NEST_TYPE_JELLY        1\r
28 #define NEST_TYPE_SYMBOL_GOOD  2\r
29 #define NEST_TYPE_SYMBOL_EVIL  3\r
30 #define NEST_TYPE_MIMIC        4\r
31 #define NEST_TYPE_LOVECRAFTIAN 5\r
32 #define NEST_TYPE_KENNEL       6\r
33 #define NEST_TYPE_ANIMAL       7\r
34 #define NEST_TYPE_CHAPEL       8\r
35 #define NEST_TYPE_UNDEAD       9\r
36 \r
37 /*! pitのID定義 / Pit types code */\r
38 #define PIT_TYPE_ORC           0\r
39 #define PIT_TYPE_TROLL         1\r
40 #define PIT_TYPE_GIANT         2\r
41 #define PIT_TYPE_LOVECRAFTIAN  3\r
42 #define PIT_TYPE_SYMBOL_GOOD   4\r
43 #define PIT_TYPE_SYMBOL_EVIL   5\r
44 #define PIT_TYPE_CHAPEL        6\r
45 #define PIT_TYPE_DRAGON        7\r
46 #define PIT_TYPE_DEMON         8\r
47 #define PIT_TYPE_DARK_ELF      9\r
48 \r
49 \r
50 \r
51 \r
52 \r
53 \r
54 /*! 通常pit生成時のモンスターの構成条件ID / Race index for "monster pit (clone)" */\r
55 static int vault_aux_race;\r
56 \r
57 /*! 単一シンボルpit生成時の指定シンボル / Race index for "monster pit (symbol clone)" */\r
58 static char vault_aux_char;\r
59 \r
60 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */\r
61 static u32b vault_aux_dragon_mask4;\r
62 \r
63 \r
64 /*!\r
65 * @brief モンスターがVault生成の最低必要条件を満たしているかを返す /\r
66 * Helper monster selection function\r
67 * @param r_idx 確認したいモンスター種族ID\r
68 * @return Vault生成の最低必要条件を満たしているならTRUEを返す。\r
69 */\r
70 static bool vault_aux_simple(MONRACE_IDX r_idx)\r
71 {\r
72         /* Okay */\r
73         return (vault_monster_okay(r_idx));\r
74 }\r
75 \r
76 \r
77 /*!\r
78 * @brief モンスターがゼリーnestの生成必要条件を満たしているかを返す /\r
79 * Helper function for "monster nest (jelly)"\r
80 * @param r_idx 確認したいモンスター種族ID\r
81 * @return 生成必要条件を満たしているならTRUEを返す。\r
82 */\r
83 static bool vault_aux_jelly(MONRACE_IDX r_idx)\r
84 {\r
85         monster_race *r_ptr = &r_info[r_idx];\r
86 \r
87         /* Validate the monster */\r
88         if (!vault_monster_okay(r_idx)) return (FALSE);\r
89 \r
90         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);\r
91 \r
92         /* Also decline evil jellies (like death molds and shoggoths) */\r
93         if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);\r
94 \r
95         /* Require icky thing, jelly, mold, or mushroom */\r
96         if (!my_strchr("ijm,", r_ptr->d_char)) return (FALSE);\r
97 \r
98         /* Okay */\r
99         return (TRUE);\r
100 }\r
101 \r
102 /*!\r
103 * @brief モンスターが動物nestの生成必要条件を満たしているかを返す /\r
104 * Helper function for "monster nest (animal)"\r
105 * @param r_idx 確認したいモンスター種族ID\r
106 * @return 生成必要条件を満たしているならTRUEを返す。\r
107 */\r
108 static bool vault_aux_animal(MONRACE_IDX r_idx)\r
109 {\r
110         monster_race *r_ptr = &r_info[r_idx];\r
111 \r
112         /* Validate the monster */\r
113         if (!vault_monster_okay(r_idx)) return (FALSE);\r
114 \r
115         /* Require "animal" flag */\r
116         if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);\r
117 \r
118         /* Okay */\r
119         return (TRUE);\r
120 }\r
121 \r
122 \r
123 /*!\r
124 * @brief モンスターがアンデッドnestの生成必要条件を満たしているかを返す /\r
125 * Helper function for "monster nest (undead)"\r
126 * @param r_idx 確認したいモンスター種族ID\r
127 * @return 生成必要条件を満たしているならTRUEを返す。\r
128 */\r
129 static bool vault_aux_undead(MONRACE_IDX r_idx)\r
130 {\r
131         monster_race *r_ptr = &r_info[r_idx];\r
132 \r
133         /* Validate the monster */\r
134         if (!vault_monster_okay(r_idx)) return (FALSE);\r
135 \r
136         /* Require Undead */\r
137         if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);\r
138 \r
139         /* Okay */\r
140         return (TRUE);\r
141 }\r
142 \r
143 /*!\r
144 * @brief モンスターが聖堂nestの生成必要条件を満たしているかを返す /\r
145 * Helper function for "monster nest (chapel)"\r
146 * @param r_idx 確認したいモンスター種族ID\r
147 * @return 生成必要条件を満たしているならTRUEを返す。\r
148 */\r
149 static bool vault_aux_chapel_g(MONRACE_IDX r_idx)\r
150 {\r
151         static int chapel_list[] = {\r
152                 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,\r
153                 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,\r
154                 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,\r
155                 MON_TOPAZ_MONK, 0 };\r
156 \r
157         int i;\r
158 \r
159         monster_race *r_ptr = &r_info[r_idx];\r
160 \r
161         /* Validate the monster */\r
162         if (!vault_monster_okay(r_idx)) return (FALSE);\r
163 \r
164         if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);\r
165         if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);\r
166 \r
167         /* Require "priest" or Angel */\r
168 \r
169         if (r_ptr->d_char == 'A') return TRUE;\r
170 \r
171         for (i = 0; chapel_list[i]; i++)\r
172                 if (r_idx == chapel_list[i]) return TRUE;\r
173 \r
174         return FALSE;\r
175 }\r
176 \r
177 /*!\r
178 * @brief モンスターが犬小屋nestの生成必要条件を満たしているかを返す /\r
179 * Helper function for "monster nest (kennel)"\r
180 * @param r_idx 確認したいモンスター種族ID\r
181 * @return 生成必要条件を満たしているならTRUEを返す。\r
182 */\r
183 static bool vault_aux_kennel(MONRACE_IDX r_idx)\r
184 {\r
185         monster_race *r_ptr = &r_info[r_idx];\r
186 \r
187         /* Validate the monster */\r
188         if (!vault_monster_okay(r_idx)) return (FALSE);\r
189 \r
190         /* Require a Zephyr Hound or a dog */\r
191         if (!my_strchr("CZ", r_ptr->d_char)) return (FALSE);\r
192 \r
193         /* Okay */\r
194         return (TRUE);\r
195 }\r
196 \r
197 /*!\r
198 * @brief モンスターがミミックnestの生成必要条件を満たしているかを返す /\r
199 * Helper function for "monster nest (mimic)"\r
200 * @param r_idx 確認したいモンスター種族ID\r
201 * @return 生成必要条件を満たしているならTRUEを返す。\r
202 */\r
203 static bool vault_aux_mimic(MONRACE_IDX r_idx)\r
204 {\r
205         monster_race *r_ptr = &r_info[r_idx];\r
206 \r
207         /* Validate the monster */\r
208         if (!vault_monster_okay(r_idx)) return (FALSE);\r
209 \r
210         /* Require mimic */\r
211         if (!my_strchr("!$&(/=?[\\|", r_ptr->d_char)) return (FALSE);\r
212 \r
213         /* Okay */\r
214         return (TRUE);\r
215 }\r
216 \r
217 /*!\r
218 * @brief モンスターが単一クローンnestの生成必要条件を満たしているかを返す /\r
219 * Helper function for "monster nest (clone)"\r
220 * @param r_idx 確認したいモンスター種族ID\r
221 * @return 生成必要条件を満たしているならTRUEを返す。\r
222 */\r
223 static bool vault_aux_clone(MONRACE_IDX r_idx)\r
224 {\r
225         /* Validate the monster */\r
226         if (!vault_monster_okay(r_idx)) return (FALSE);\r
227 \r
228         return (r_idx == vault_aux_race);\r
229 }\r
230 \r
231 \r
232 /*!\r
233 * @brief モンスターが邪悪属性シンボルクローンnestの生成必要条件を満たしているかを返す /\r
234 * Helper function for "monster nest (symbol clone)"\r
235 * @param r_idx 確認したいモンスター種族ID\r
236 * @return 生成必要条件を満たしているならTRUEを返す。\r
237 */\r
238 static bool vault_aux_symbol_e(MONRACE_IDX r_idx)\r
239 {\r
240         monster_race *r_ptr = &r_info[r_idx];\r
241 \r
242         /* Validate the monster */\r
243         if (!vault_monster_okay(r_idx)) return (FALSE);\r
244 \r
245         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);\r
246 \r
247         if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);\r
248 \r
249         /* Decline incorrect symbol */\r
250         if (r_ptr->d_char != vault_aux_char) return (FALSE);\r
251 \r
252         /* Okay */\r
253         return (TRUE);\r
254 }\r
255 \r
256 \r
257 /*!\r
258 * @brief モンスターが善良属性シンボルクローンnestの生成必要条件を満たしているかを返す /\r
259 * Helper function for "monster nest (symbol clone)"\r
260 * @param r_idx 確認したいモンスター種族ID\r
261 * @return 生成必要条件を満たしているならTRUEを返す。\r
262 */\r
263 static bool vault_aux_symbol_g(MONRACE_IDX r_idx)\r
264 {\r
265         monster_race *r_ptr = &r_info[r_idx];\r
266 \r
267         /* Validate the monster */\r
268         if (!vault_monster_okay(r_idx)) return (FALSE);\r
269 \r
270         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);\r
271 \r
272         if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);\r
273 \r
274         /* Decline incorrect symbol */\r
275         if (r_ptr->d_char != vault_aux_char) return (FALSE);\r
276 \r
277         /* Okay */\r
278         return (TRUE);\r
279 }\r
280 \r
281 \r
282 /*!\r
283 * @brief モンスターがオークpitの生成必要条件を満たしているかを返す /\r
284 * Helper function for "monster pit (orc)"\r
285 * @param r_idx 確認したいモンスター種族ID\r
286 * @return 生成必要条件を満たしているならTRUEを返す。\r
287 */\r
288 static bool vault_aux_orc(MONRACE_IDX r_idx)\r
289 {\r
290         monster_race *r_ptr = &r_info[r_idx];\r
291 \r
292         /* Validate the monster */\r
293         if (!vault_monster_okay(r_idx)) return (FALSE);\r
294 \r
295         /* Require orc */\r
296         if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);\r
297 \r
298         /* Decline undead */\r
299         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);\r
300 \r
301         /* Okay */\r
302         return (TRUE);\r
303 }\r
304 \r
305 \r
306 /*!\r
307 * @brief モンスターがトロルpitの生成必要条件を満たしているかを返す /\r
308 * Helper function for "monster pit (troll)"\r
309 * @param r_idx 確認したいモンスター種族ID\r
310 * @return 生成必要条件を満たしているならTRUEを返す。\r
311 */\r
312 static bool vault_aux_troll(MONRACE_IDX r_idx)\r
313 {\r
314         monster_race *r_ptr = &r_info[r_idx];\r
315 \r
316         /* Validate the monster */\r
317         if (!vault_monster_okay(r_idx)) return (FALSE);\r
318 \r
319         /* Require troll */\r
320         if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);\r
321 \r
322         /* Decline undead */\r
323         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);\r
324 \r
325         /* Okay */\r
326         return (TRUE);\r
327 }\r
328 \r
329 \r
330 /*!\r
331 * @brief モンスターが巨人pitの生成必要条件を満たしているかを返す /\r
332 * Helper function for "monster pit (giant)"\r
333 * @param r_idx 確認したいモンスター種族ID\r
334 * @return 生成必要条件を満たしているならTRUEを返す。\r
335 */\r
336 static bool vault_aux_giant(MONRACE_IDX r_idx)\r
337 {\r
338         monster_race *r_ptr = &r_info[r_idx];\r
339 \r
340         /* Validate the monster */\r
341         if (!vault_monster_okay(r_idx)) return (FALSE);\r
342 \r
343         /* Require giant */\r
344         if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);\r
345 \r
346         if (r_ptr->flags3 & RF3_GOOD) return (FALSE);\r
347 \r
348         /* Decline undead */\r
349         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);\r
350 \r
351         /* Okay */\r
352         return (TRUE);\r
353 }\r
354 \r
355 \r
356 /*!\r
357 * @brief モンスターがドラゴンpitの生成必要条件を満たしているかを返す /\r
358 * Helper function for "monster pit (dragon)"\r
359 * @param r_idx 確認したいモンスター種族ID\r
360 * @return 生成必要条件を満たしているならTRUEを返す。\r
361 */\r
362 static bool vault_aux_dragon(MONRACE_IDX r_idx)\r
363 {\r
364         monster_race *r_ptr = &r_info[r_idx];\r
365 \r
366         /* Validate the monster */\r
367         if (!vault_monster_okay(r_idx)) return (FALSE);\r
368 \r
369         /* Require dragon */\r
370         if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);\r
371 \r
372         /* Hack -- Require correct "breath attack" */\r
373         if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);\r
374 \r
375         /* Decline undead */\r
376         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);\r
377 \r
378         /* Okay */\r
379         return (TRUE);\r
380 }\r
381 \r
382 \r
383 /*!\r
384 * @brief モンスターが悪魔pitの生成必要条件を満たしているかを返す /\r
385 * Helper function for "monster pit (demon)"\r
386 * @param r_idx 確認したいモンスター種族ID\r
387 * @return 生成必要条件を満たしているならTRUEを返す。\r
388 */\r
389 static bool vault_aux_demon(MONRACE_IDX r_idx)\r
390 {\r
391         monster_race *r_ptr = &r_info[r_idx];\r
392 \r
393         /* Validate the monster */\r
394         if (!vault_monster_okay(r_idx)) return (FALSE);\r
395 \r
396         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);\r
397 \r
398         /* Require demon */\r
399         if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);\r
400 \r
401         /* Okay */\r
402         return (TRUE);\r
403 }\r
404 \r
405 \r
406 /*!\r
407 * @brief モンスターが狂気pitの生成必要条件を満たしているかを返す /\r
408 * Helper function for "monster pit (lovecraftian)"\r
409 * @param r_idx 確認したいモンスター種族ID\r
410 * @return 生成必要条件を満たしているならTRUEを返す。\r
411 */\r
412 static bool vault_aux_cthulhu(MONRACE_IDX r_idx)\r
413 {\r
414         monster_race *r_ptr = &r_info[r_idx];\r
415 \r
416         /* Validate the monster */\r
417         if (!vault_monster_okay(r_idx)) return (FALSE);\r
418 \r
419         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);\r
420 \r
421         /* Require eldritch horror */\r
422         if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);\r
423 \r
424         /* Okay */\r
425         return (TRUE);\r
426 }\r
427 \r
428 \r
429 /*!\r
430 * @brief pit/nestの基準となる単種モンスターを決める /\r
431 * @return なし\r
432 */\r
433 static void vault_prep_clone(void)\r
434 {\r
435         /* Apply the monster restriction */\r
436         get_mon_num_prep(vault_aux_simple, NULL);\r
437 \r
438         /* Pick a race to clone */\r
439         vault_aux_race = get_mon_num(dun_level + 10);\r
440 \r
441         /* Remove the monster restriction */\r
442         get_mon_num_prep(NULL, NULL);\r
443 }\r
444 \r
445 \r
446 /*!\r
447 * @brief pit/nestの基準となるモンスターシンボルを決める /\r
448 * @return なし\r
449 */\r
450 static void vault_prep_symbol(void)\r
451 {\r
452         MONRACE_IDX r_idx;\r
453 \r
454         /* Apply the monster restriction */\r
455         get_mon_num_prep(vault_aux_simple, NULL);\r
456 \r
457         /* Pick a race to clone */\r
458         r_idx = get_mon_num(dun_level + 10);\r
459 \r
460         /* Remove the monster restriction */\r
461         get_mon_num_prep(NULL, NULL);\r
462 \r
463         /* Extract the symbol */\r
464         vault_aux_char = r_info[r_idx].d_char;\r
465 }\r
466 \r
467 /*!\r
468 * @brief pit/nestの基準となるドラゴンの種類を決める /\r
469 * @return なし\r
470 */\r
471 static void vault_prep_dragon(void)\r
472 {\r
473         /* Pick dragon type */\r
474         switch (randint0(6))\r
475         {\r
476                 /* Black */\r
477         case 0:\r
478         {\r
479                 /* Restrict dragon breath type */\r
480                 vault_aux_dragon_mask4 = RF4_BR_ACID;\r
481 \r
482                 break;\r
483         }\r
484 \r
485         /* Blue */\r
486         case 1:\r
487         {\r
488                 /* Restrict dragon breath type */\r
489                 vault_aux_dragon_mask4 = RF4_BR_ELEC;\r
490 \r
491                 break;\r
492         }\r
493 \r
494         /* Red */\r
495         case 2:\r
496         {\r
497                 /* Restrict dragon breath type */\r
498                 vault_aux_dragon_mask4 = RF4_BR_FIRE;\r
499 \r
500                 break;\r
501         }\r
502 \r
503         /* White */\r
504         case 3:\r
505         {\r
506                 /* Restrict dragon breath type */\r
507                 vault_aux_dragon_mask4 = RF4_BR_COLD;\r
508 \r
509                 break;\r
510         }\r
511 \r
512         /* Green */\r
513         case 4:\r
514         {\r
515                 /* Restrict dragon breath type */\r
516                 vault_aux_dragon_mask4 = RF4_BR_POIS;\r
517 \r
518                 break;\r
519         }\r
520 \r
521         /* Multi-hued */\r
522         default:\r
523         {\r
524                 /* Restrict dragon breath type */\r
525                 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |\r
526                         RF4_BR_FIRE | RF4_BR_COLD |\r
527                         RF4_BR_POIS);\r
528 \r
529                 break;\r
530         }\r
531         }\r
532 }\r
533 \r
534 \r
535 /*!\r
536 * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /\r
537 * Helper function for "monster pit (dark elf)"\r
538 * @param r_idx 確認したいモンスター種族ID\r
539 * @return 生成必要条件を満たしているならTRUEを返す。\r
540 */\r
541 static bool vault_aux_dark_elf(MONRACE_IDX r_idx)\r
542 {\r
543         int i;\r
544         static int dark_elf_list[] =\r
545         {\r
546                 MON_D_ELF, MON_D_ELF_MAGE, MON_D_ELF_WARRIOR, MON_D_ELF_PRIEST,\r
547                 MON_D_ELF_LORD, MON_D_ELF_WARLOCK, MON_D_ELF_DRUID, MON_NIGHTBLADE,\r
548                 MON_D_ELF_SORC, MON_D_ELF_SHADE, 0,\r
549         };\r
550 \r
551         /* Validate the monster */\r
552         if (!vault_monster_okay(r_idx)) return FALSE;\r
553 \r
554         /* Require dark elves */\r
555         for (i = 0; dark_elf_list[i]; i++)\r
556                 if (r_idx == dark_elf_list[i]) return TRUE;\r
557 \r
558         /* Assume not */\r
559         return FALSE;\r
560 }\r
561 \r
562 \r
563 /*!\r
564 * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める\r
565 * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ\r
566 * @param allow_flag_mask 生成が許されるpit/nestのビット配列\r
567 * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。\r
568 */\r
569 static int pick_vault_type(vault_aux_type *l_ptr, BIT_FLAGS16 allow_flag_mask)\r
570 {\r
571         int tmp, total, count;\r
572 \r
573         vault_aux_type *n_ptr;\r
574 \r
575         /* Calculate the total possibilities */\r
576         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)\r
577         {\r
578                 /* Note end */\r
579                 if (!n_ptr->name) break;\r
580 \r
581                 /* Ignore excessive depth */\r
582                 if (n_ptr->level > dun_level) continue;\r
583 \r
584                 /* Not matched with pit/nest flag */\r
585                 if (!(allow_flag_mask & (1L << count))) continue;\r
586 \r
587                 /* Count this possibility */\r
588                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);\r
589         }\r
590 \r
591         /* Pick a random type */\r
592         tmp = randint0(total);\r
593 \r
594         /* Find this type */\r
595         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)\r
596         {\r
597                 /* Note end */\r
598                 if (!n_ptr->name) break;\r
599 \r
600                 /* Ignore excessive depth */\r
601                 if (n_ptr->level > dun_level) continue;\r
602 \r
603                 /* Not matched with pit/nest flag */\r
604                 if (!(allow_flag_mask & (1L << count))) continue;\r
605 \r
606                 /* Count this possibility */\r
607                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);\r
608 \r
609                 /* Found the type */\r
610                 if (tmp < total) break;\r
611         }\r
612 \r
613         return n_ptr->name ? count : -1;\r
614 }\r
615 \r
616 /*!\r
617 * @brief デバッグ時に生成されたpit/nestの型を出力する処理\r
618 * @param type pit/nestの型ID\r
619 * @param nest TRUEならばnest、FALSEならばpit\r
620 * @return デバッグ表示文字列の参照ポインタ\r
621 * @details\r
622 * Hack -- Get the string describing subtype of pit/nest\r
623 * Determined in prepare function (some pit/nest only)\r
624 */\r
625 static cptr pit_subtype_string(int type, bool nest)\r
626 {\r
627         static char inner_buf[256] = "";\r
628 \r
629         inner_buf[0] = '\0'; /* Init string */\r
630 \r
631         if (nest) /* Nests */\r
632         {\r
633                 switch (type)\r
634                 {\r
635                 case NEST_TYPE_CLONE:\r
636                         sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);\r
637                         break;\r
638                 case NEST_TYPE_SYMBOL_GOOD:\r
639                 case NEST_TYPE_SYMBOL_EVIL:\r
640                         sprintf(inner_buf, "(%c)", vault_aux_char);\r
641                         break;\r
642                 }\r
643         }\r
644         else /* Pits */\r
645         {\r
646                 switch (type)\r
647                 {\r
648                 case PIT_TYPE_SYMBOL_GOOD:\r
649                 case PIT_TYPE_SYMBOL_EVIL:\r
650                         sprintf(inner_buf, "(%c)", vault_aux_char);\r
651                         break;\r
652                 case PIT_TYPE_DRAGON:\r
653                         switch (vault_aux_dragon_mask4)\r
654                         {\r
655                                 case RF4_BR_ACID: strcpy(inner_buf, _("(酸)", "(acid)"));   break;\r
656                                 case RF4_BR_ELEC: strcpy(inner_buf, _("(稲妻)", "(lightning)")); break;\r
657                                 case RF4_BR_FIRE: strcpy(inner_buf, _("(火炎)", "(fire)")); break;\r
658                                 case RF4_BR_COLD: strcpy(inner_buf, _("(冷気)", "(frost)")); break;\r
659                                 case RF4_BR_POIS: strcpy(inner_buf, _("(毒)", "(poison)"));   break;\r
660                                 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS) :\r
661                                         strcpy(inner_buf, _("(万色)", "(multi-hued)")); break;\r
662                                 default: strcpy(inner_buf, _("(未定義)", "(undefined)")); break;\r
663                         }\r
664                         break;\r
665                 }\r
666         }\r
667 \r
668         return inner_buf;\r
669 }\r
670 \r
671 \r
672 \r
673 \r
674 \r
675 /*\r
676 *! @brief nestのモンスターリストをソートするための関数 /\r
677 *  Comp function for sorting nest monster information\r
678 *  @param u ソート処理対象配列ポインタ\r
679 *  @param v 未使用\r
680 *  @param a 比較対象参照ID1\r
681 *  @param b 比較対象参照ID2\r
682 */\r
683 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)\r
684 {\r
685         nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;\r
686         MONSTER_IDX w1 = nest_mon_info[a].r_idx;\r
687         MONSTER_IDX w2 = nest_mon_info[b].r_idx;\r
688         monster_race *r1_ptr = &r_info[w1];\r
689         monster_race *r2_ptr = &r_info[w2];\r
690         int z1, z2;\r
691 \r
692         /* Unused */\r
693         (void)v;\r
694 \r
695         /* Extract used info */\r
696         z1 = nest_mon_info[a].used;\r
697         z2 = nest_mon_info[b].used;\r
698 \r
699         /* Compare used status */\r
700         if (z1 < z2) return FALSE;\r
701         if (z1 > z2) return TRUE;\r
702 \r
703         /* Compare levels */\r
704         if (r1_ptr->level < r2_ptr->level) return TRUE;\r
705         if (r1_ptr->level > r2_ptr->level) return FALSE;\r
706 \r
707         /* Compare experience */\r
708         if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;\r
709         if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;\r
710 \r
711         /* Compare indexes */\r
712         return w1 <= w2;\r
713 }\r
714 \r
715 /*!\r
716 * @brief nestのモンスターリストをスワップするための関数 /\r
717 * Swap function for sorting nest monster information\r
718 * @param u スワップ処理対象配列ポインタ\r
719 * @param v 未使用\r
720 * @param a スワップ対象参照ID1\r
721 * @param b スワップ対象参照ID2\r
722 */\r
723 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)\r
724 {\r
725         nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;\r
726         nest_mon_info_type holder;\r
727 \r
728         /* Unused */\r
729         (void)v;\r
730 \r
731         /* Swap */\r
732         holder = nest_mon_info[a];\r
733         nest_mon_info[a] = nest_mon_info[b];\r
734         nest_mon_info[b] = holder;\r
735 }\r
736 \r
737 \r
738 \r
739 /*!nest情報テーブル*/\r
740 static vault_aux_type nest_types[] =\r
741 {\r
742         { _("クローン", "clone"),      vault_aux_clone,    vault_prep_clone,   5, 3 },\r
743         { _("ゼリー", "jelly"),        vault_aux_jelly,    NULL,               5, 6 },\r
744         { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 25, 2 },\r
745         { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 25, 2 },\r
746         { _("ミミック", "mimic"),      vault_aux_mimic,    NULL,              30, 4 },\r
747         { _("狂気", "lovecraftian"),   vault_aux_cthulhu,  NULL,              70, 2 },\r
748         { _("犬小屋", "kennel"),       vault_aux_kennel,   NULL,              45, 4 },\r
749         { _("動物園", "animal"),       vault_aux_animal,   NULL,              35, 5 },\r
750         { _("教会", "chapel"),         vault_aux_chapel_g, NULL,              75, 4 },\r
751         { _("アンデッド", "undead"),   vault_aux_undead,   NULL,              75, 5 },\r
752         { NULL,           NULL,               NULL,               0, 0 },\r
753 };\r
754 \r
755 /*!pit情報テーブル*/\r
756 static vault_aux_type pit_types[] =\r
757 {\r
758         { _("オーク", "orc"),            vault_aux_orc,      NULL,               5, 6 },\r
759         { _("トロル", "troll"),          vault_aux_troll,    NULL,              20, 6 },\r
760         { _("ジャイアント", "giant"),    vault_aux_giant,    NULL,              50, 6 },\r
761         { _("狂気", "lovecraftian"),     vault_aux_cthulhu,  NULL,              80, 2 },\r
762         { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 70, 1 },\r
763         { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 70, 1 },\r
764         { _("教会", "chapel"),           vault_aux_chapel_g, NULL,              65, 2 },\r
765         { _("ドラゴン", "dragon"),       vault_aux_dragon,   vault_prep_dragon, 70, 6 },\r
766         { _("デーモン", "demon"),        vault_aux_demon,    NULL,              80, 6 },\r
767         { _("ダークエルフ", "dark elf"), vault_aux_dark_elf, NULL,              45, 4 },\r
768         { NULL,           NULL,               NULL,               0, 0 },\r
769 };\r
770 \r
771 \r
772 \r
773 \r
774 /*!\r
775 * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests\r
776 * @return なし\r
777 * @details\r
778 * A monster nest is a "big" room, with an "inner" room, containing\n\r
779 * a "collection" of monsters of a given type strewn about the room.\n\r
780 *\n\r
781 * The monsters are chosen from a set of 64 randomly selected monster\n\r
782 * races, to allow the nest creation to fail instead of having "holes".\n\r
783 *\n\r
784 * Note the use of the "get_mon_num_prep()" function, and the special\n\r
785 * "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
786 * allocation table" in such a way as to optimize the selection of\n\r
787 * "appropriate" non-unique monsters for the nest.\n\r
788 *\n\r
789 * Note that the "get_mon_num()" function may (rarely) fail, in which\n\r
790 * case the nest will be empty.\n\r
791 *\n\r
792 * Note that "monster nests" will never contain "unique" monsters.\n\r
793 */\r
794 bool build_type5(void)\r
795 {\r
796         POSITION y, x, y1, x1, y2, x2, xval, yval;\r
797         int i;\r
798         nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];\r
799 \r
800         monster_type align;\r
801 \r
802         cave_type *c_ptr;\r
803 \r
804         int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);\r
805         vault_aux_type *n_ptr;\r
806 \r
807         /* No type available */\r
808         if (cur_nest_type < 0) return FALSE;\r
809 \r
810         n_ptr = &nest_types[cur_nest_type];\r
811 \r
812         /* Process a preparation function if necessary */\r
813         if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
814 \r
815         /* Prepare allocation table */\r
816         get_mon_num_prep(n_ptr->hook_func, NULL);\r
817 \r
818         align.sub_align = SUB_ALIGN_NEUTRAL;\r
819 \r
820         /* Pick some monster types */\r
821         for (i = 0; i < NUM_NEST_MON_TYPE; i++)\r
822         {\r
823                 MONRACE_IDX r_idx = 0;\r
824                 int attempts = 100;\r
825                 monster_race *r_ptr = NULL;\r
826 \r
827                 while (attempts--)\r
828                 {\r
829                         /* Get a (hard) monster type */\r
830                         r_idx = get_mon_num(dun_level + 11);\r
831                         r_ptr = &r_info[r_idx];\r
832 \r
833                         /* Decline incorrect alignment */\r
834                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
835 \r
836                         /* Accept this monster */\r
837                         break;\r
838                 }\r
839 \r
840                 /* Notice failure */\r
841                 if (!r_idx || !attempts) return FALSE;\r
842 \r
843                 /* Note the alignment */\r
844                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
845                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
846 \r
847                 nest_mon_info[i].r_idx = (s16b)r_idx;\r
848                 nest_mon_info[i].used = FALSE;\r
849         }\r
850 \r
851         /* Find and reserve some space in the dungeon.  Get center of room. */\r
852         if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
853 \r
854         /* Large room */\r
855         y1 = yval - 4;\r
856         y2 = yval + 4;\r
857         x1 = xval - 11;\r
858         x2 = xval + 11;\r
859 \r
860         /* Place the floor area */\r
861         for (y = y1 - 1; y <= y2 + 1; y++)\r
862         {\r
863                 for (x = x1 - 1; x <= x2 + 1; x++)\r
864                 {\r
865                         c_ptr = &cave[y][x];\r
866                         place_floor_grid(c_ptr);\r
867                         c_ptr->info |= (CAVE_ROOM);\r
868                 }\r
869         }\r
870 \r
871         /* Place the outer walls */\r
872         for (y = y1 - 1; y <= y2 + 1; y++)\r
873         {\r
874                 c_ptr = &cave[y][x1 - 1];\r
875                 place_outer_grid(c_ptr);\r
876                 c_ptr = &cave[y][x2 + 1];\r
877                 place_outer_grid(c_ptr);\r
878         }\r
879         for (x = x1 - 1; x <= x2 + 1; x++)\r
880         {\r
881                 c_ptr = &cave[y1 - 1][x];\r
882                 place_outer_grid(c_ptr);\r
883                 c_ptr = &cave[y2 + 1][x];\r
884                 place_outer_grid(c_ptr);\r
885         }\r
886 \r
887 \r
888         /* Advance to the center room */\r
889         y1 = y1 + 2;\r
890         y2 = y2 - 2;\r
891         x1 = x1 + 2;\r
892         x2 = x2 - 2;\r
893 \r
894         /* The inner walls */\r
895         for (y = y1 - 1; y <= y2 + 1; y++)\r
896         {\r
897                 c_ptr = &cave[y][x1 - 1];\r
898                 place_inner_grid(c_ptr);\r
899                 c_ptr = &cave[y][x2 + 1];\r
900                 place_inner_grid(c_ptr);\r
901         }\r
902 \r
903         for (x = x1 - 1; x <= x2 + 1; x++)\r
904         {\r
905                 c_ptr = &cave[y1 - 1][x];\r
906                 place_inner_grid(c_ptr);\r
907                 c_ptr = &cave[y2 + 1][x];\r
908                 place_inner_grid(c_ptr);\r
909         }\r
910         for (y = y1; y <= y2; y++)\r
911         {\r
912                 for (x = x1; x <= x2; x++)\r
913                 {\r
914                         add_cave_info(y, x, CAVE_ICKY);\r
915                 }\r
916         }\r
917 \r
918         /* Place a secret door */\r
919         switch (randint1(4))\r
920         {\r
921         case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
922         case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
923         case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
924         case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
925         }\r
926 \r
927         msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));\r
928 \r
929         /* Place some monsters */\r
930         for (y = yval - 2; y <= yval + 2; y++)\r
931         {\r
932                 for (x = xval - 9; x <= xval + 9; x++)\r
933                 {\r
934                         MONRACE_IDX r_idx;\r
935 \r
936                         i = randint0(NUM_NEST_MON_TYPE);\r
937                         r_idx = nest_mon_info[i].r_idx;\r
938 \r
939                         /* Place that "random" monster (no groups) */\r
940                         (void)place_monster_aux(0, y, x, r_idx, 0L);\r
941 \r
942                         nest_mon_info[i].used = TRUE;\r
943                 }\r
944         }\r
945 \r
946         if (cheat_room)\r
947         {\r
948                 ang_sort_comp = ang_sort_comp_nest_mon_info;\r
949                 ang_sort_swap = ang_sort_swap_nest_mon_info;\r
950                 ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);\r
951 \r
952                 /* Dump the entries (prevent multi-printing) */\r
953                 for (i = 0; i < NUM_NEST_MON_TYPE; i++)\r
954                 {\r
955                         if (!nest_mon_info[i].used) break;\r
956                         for (; i < NUM_NEST_MON_TYPE - 1; i++)\r
957                         {\r
958                                 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;\r
959                                 if (!nest_mon_info[i + 1].used) break;\r
960                         }\r
961                         msg_format_wizard(CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);\r
962                 }\r
963         }\r
964 \r
965         return TRUE;\r
966 }\r
967 \r
968 \r
969 /*!\r
970 * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits\r
971 * @return なし\r
972 * @details\r
973 * A monster pit is a "big" room, with an "inner" room, containing\n\r
974 * a "collection" of monsters of a given type organized in the room.\n\r
975 *\n\r
976 * The inside room in a monster pit appears as shown below, where the\n\r
977 * actual monsters in each location depend on the type of the pit\n\r
978 *\n\r
979 *   XXXXXXXXXXXXXXXXXXXXX\n\r
980 *   X0000000000000000000X\n\r
981 *   X0112233455543322110X\n\r
982 *   X0112233467643322110X\n\r
983 *   X0112233455543322110X\n\r
984 *   X0000000000000000000X\n\r
985 *   XXXXXXXXXXXXXXXXXXXXX\n\r
986 *\n\r
987 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n\r
988 * to request 16 "appropriate" monsters, sorting them by level, and using\n\r
989 * the "even" entries in this sorted list for the contents of the pit.\n\r
990 *\n\r
991 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n\r
992 * which is handled by requiring a specific "breath" attack for all of the\n\r
993 * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n\r
994 * be present in many of the dragon pits, if they have the proper breath.\n\r
995 *\n\r
996 * Note the use of the "get_mon_num_prep()" function, and the special\n\r
997 * "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
998 * allocation table" in such a way as to optimize the selection of\n\r
999 * "appropriate" non-unique monsters for the pit.\n\r
1000 *\n\r
1001 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n\r
1002 * the pit will be empty.\n\r
1003 *\n\r
1004 * Note that "monster pits" will never contain "unique" monsters.\n\r
1005 */\r
1006 bool build_type6(void)\r
1007 {\r
1008         POSITION y, x, y1, x1, y2, x2, xval, yval;\r
1009         int i, j;\r
1010 \r
1011         MONRACE_IDX what[16];\r
1012 \r
1013         monster_type align;\r
1014 \r
1015         cave_type *c_ptr;\r
1016 \r
1017         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);\r
1018         vault_aux_type *n_ptr;\r
1019 \r
1020         /* No type available */\r
1021         if (cur_pit_type < 0) return FALSE;\r
1022 \r
1023         n_ptr = &pit_types[cur_pit_type];\r
1024 \r
1025         /* Process a preparation function if necessary */\r
1026         if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
1027 \r
1028         /* Prepare allocation table */\r
1029         get_mon_num_prep(n_ptr->hook_func, NULL);\r
1030 \r
1031         align.sub_align = SUB_ALIGN_NEUTRAL;\r
1032 \r
1033         /* Pick some monster types */\r
1034         for (i = 0; i < 16; i++)\r
1035         {\r
1036                 MONRACE_IDX r_idx = 0;\r
1037                 int attempts = 100;\r
1038                 monster_race *r_ptr = NULL;\r
1039 \r
1040                 while (attempts--)\r
1041                 {\r
1042                         /* Get a (hard) monster type */\r
1043                         r_idx = get_mon_num(dun_level + 11);\r
1044                         r_ptr = &r_info[r_idx];\r
1045 \r
1046                         /* Decline incorrect alignment */\r
1047                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
1048 \r
1049                         /* Accept this monster */\r
1050                         break;\r
1051                 }\r
1052 \r
1053                 /* Notice failure */\r
1054                 if (!r_idx || !attempts) return FALSE;\r
1055 \r
1056                 /* Note the alignment */\r
1057                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
1058                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
1059 \r
1060                 what[i] = r_idx;\r
1061         }\r
1062 \r
1063         /* Find and reserve some space in the dungeon.  Get center of room. */\r
1064         if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
1065 \r
1066         /* Large room */\r
1067         y1 = yval - 4;\r
1068         y2 = yval + 4;\r
1069         x1 = xval - 11;\r
1070         x2 = xval + 11;\r
1071 \r
1072         /* Place the floor area */\r
1073         for (y = y1 - 1; y <= y2 + 1; y++)\r
1074         {\r
1075                 for (x = x1 - 1; x <= x2 + 1; x++)\r
1076                 {\r
1077                         c_ptr = &cave[y][x];\r
1078                         place_floor_grid(c_ptr);\r
1079                         c_ptr->info |= (CAVE_ROOM);\r
1080                 }\r
1081         }\r
1082 \r
1083         /* Place the outer walls */\r
1084         for (y = y1 - 1; y <= y2 + 1; y++)\r
1085         {\r
1086                 c_ptr = &cave[y][x1 - 1];\r
1087                 place_outer_grid(c_ptr);\r
1088                 c_ptr = &cave[y][x2 + 1];\r
1089                 place_outer_grid(c_ptr);\r
1090         }\r
1091         for (x = x1 - 1; x <= x2 + 1; x++)\r
1092         {\r
1093                 c_ptr = &cave[y1 - 1][x];\r
1094                 place_outer_grid(c_ptr);\r
1095                 c_ptr = &cave[y2 + 1][x];\r
1096                 place_outer_grid(c_ptr);\r
1097         }\r
1098 \r
1099         /* Advance to the center room */\r
1100         y1 = y1 + 2;\r
1101         y2 = y2 - 2;\r
1102         x1 = x1 + 2;\r
1103         x2 = x2 - 2;\r
1104 \r
1105         /* The inner walls */\r
1106         for (y = y1 - 1; y <= y2 + 1; y++)\r
1107         {\r
1108                 c_ptr = &cave[y][x1 - 1];\r
1109                 place_inner_grid(c_ptr);\r
1110                 c_ptr = &cave[y][x2 + 1];\r
1111                 place_inner_grid(c_ptr);\r
1112         }\r
1113         for (x = x1 - 1; x <= x2 + 1; x++)\r
1114         {\r
1115                 c_ptr = &cave[y1 - 1][x];\r
1116                 place_inner_grid(c_ptr);\r
1117                 c_ptr = &cave[y2 + 1][x];\r
1118                 place_inner_grid(c_ptr);\r
1119         }\r
1120         for (y = y1; y <= y2; y++)\r
1121         {\r
1122                 for (x = x1; x <= x2; x++)\r
1123                 {\r
1124                         add_cave_info(y, x, CAVE_ICKY);\r
1125                 }\r
1126         }\r
1127 \r
1128         /* Place a secret door */\r
1129         switch (randint1(4))\r
1130         {\r
1131         case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
1132         case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
1133         case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
1134         case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
1135         }\r
1136 \r
1137         /* Sort the entries */\r
1138         for (i = 0; i < 16 - 1; i++)\r
1139         {\r
1140                 /* Sort the entries */\r
1141                 for (j = 0; j < 16 - 1; j++)\r
1142                 {\r
1143                         int i1 = j;\r
1144                         int i2 = j + 1;\r
1145 \r
1146                         int p1 = r_info[what[i1]].level;\r
1147                         int p2 = r_info[what[i2]].level;\r
1148 \r
1149                         /* Bubble */\r
1150                         if (p1 > p2)\r
1151                         {\r
1152                                 MONRACE_IDX tmp = what[i1];\r
1153                                 what[i1] = what[i2];\r
1154                                 what[i2] = tmp;\r
1155                         }\r
1156                 }\r
1157         }\r
1158 \r
1159         msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));\r
1160 \r
1161         /* Select the entries */\r
1162         for (i = 0; i < 8; i++)\r
1163         {\r
1164                 /* Every other entry */\r
1165                 what[i] = what[i * 2];\r
1166                 msg_format_wizard(CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);\r
1167         }\r
1168 \r
1169         /* Top and bottom rows */\r
1170         for (x = xval - 9; x <= xval + 9; x++)\r
1171         {\r
1172                 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);\r
1173                 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);\r
1174         }\r
1175 \r
1176         /* Middle columns */\r
1177         for (y = yval - 1; y <= yval + 1; y++)\r
1178         {\r
1179                 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);\r
1180                 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);\r
1181 \r
1182                 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);\r
1183                 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);\r
1184 \r
1185                 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);\r
1186                 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);\r
1187 \r
1188                 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);\r
1189                 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);\r
1190 \r
1191                 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);\r
1192                 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);\r
1193 \r
1194                 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);\r
1195                 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);\r
1196 \r
1197                 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);\r
1198                 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);\r
1199 \r
1200                 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);\r
1201                 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);\r
1202         }\r
1203 \r
1204         /* Above/Below the center monster */\r
1205         for (x = xval - 1; x <= xval + 1; x++)\r
1206         {\r
1207                 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);\r
1208                 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);\r
1209         }\r
1210 \r
1211         /* Next to the center monster */\r
1212         place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);\r
1213         place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);\r
1214 \r
1215         /* Center monster */\r
1216         place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);\r
1217 \r
1218         return TRUE;\r
1219 }\r
1220 \r
1221 \r
1222 \r
1223 /*\r
1224 * Helper function for "trapped monster pit"\r
1225 */\r
1226 static bool vault_aux_trapped_pit(MONRACE_IDX r_idx)\r
1227 {\r
1228         monster_race *r_ptr = &r_info[r_idx];\r
1229 \r
1230         /* Validate the monster */\r
1231         if (!vault_monster_okay(r_idx)) return (FALSE);\r
1232 \r
1233         /* No wall passing monster */\r
1234         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);\r
1235 \r
1236         /* Okay */\r
1237         return (TRUE);\r
1238 }\r
1239 \r
1240 \r
1241 /*!\r
1242 * @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits\r
1243 * @return なし\r
1244 * @details\r
1245 * A trapped monster pit is a "big" room with a straight corridor in\n\r
1246 * which wall opening traps are placed, and with two "inner" rooms\n\r
1247 * containing a "collection" of monsters of a given type organized in\n\r
1248 * the room.\n\r
1249 *\n\r
1250 * The trapped monster pit appears as shown below, where the actual\n\r
1251 * monsters in each location depend on the type of the pit\n\r
1252 *\n\r
1253 *  XXXXXXXXXXXXXXXXXXXXXXXXX\n\r
1254 *  X                       X\n\r
1255 *  XXXXXXXXXXXXXXXXXXXXXXX X\n\r
1256 *  XXXXX001123454321100XXX X\n\r
1257 *  XXX0012234567654322100X X\n\r
1258 *  XXXXXXXXXXXXXXXXXXXXXXX X\n\r
1259 *  X           ^           X\n\r
1260 *  X XXXXXXXXXXXXXXXXXXXXXXX\n\r
1261 *  X X0012234567654322100XXX\n\r
1262 *  X XXX001123454321100XXXXX\n\r
1263 *  X XXXXXXXXXXXXXXXXXXXXXXX\n\r
1264 *  X                       X\n\r
1265 *  XXXXXXXXXXXXXXXXXXXXXXXXX\n\r
1266 *\n\r
1267 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n\r
1268 * to request 16 "appropriate" monsters, sorting them by level, and using\n\r
1269 * the "even" entries in this sorted list for the contents of the pit.\n\r
1270 *\n\r
1271 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n\r
1272 * which is handled by requiring a specific "breath" attack for all of the\n\r
1273 * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n\r
1274 * be present in many of the dragon pits, if they have the proper breath.\n\r
1275 *\n\r
1276 * Note the use of the "get_mon_num_prep()" function, and the special\n\r
1277 * "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
1278 * allocation table" in such a way as to optimize the selection of\n\r
1279 * "appropriate" non-unique monsters for the pit.\n\r
1280 *\n\r
1281 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n\r
1282 * the pit will be empty.\n\r
1283 *\n\r
1284 * Note that "monster pits" will never contain "unique" monsters.\n\r
1285 */\r
1286 bool build_type13(void)\r
1287 {\r
1288         static int placing[][3] = {\r
1289                 { -2, -9, 0 },{ -2, -8, 0 },{ -3, -7, 0 },{ -3, -6, 0 },\r
1290                 { +2, -9, 0 },{ +2, -8, 0 },{ +3, -7, 0 },{ +3, -6, 0 },\r
1291                 { -2, +9, 0 },{ -2, +8, 0 },{ -3, +7, 0 },{ -3, +6, 0 },\r
1292                 { +2, +9, 0 },{ +2, +8, 0 },{ +3, +7, 0 },{ +3, +6, 0 },\r
1293                 { -2, -7, 1 },{ -3, -5, 1 },{ -3, -4, 1 },\r
1294                 { +2, -7, 1 },{ +3, -5, 1 },{ +3, -4, 1 },\r
1295                 { -2, +7, 1 },{ -3, +5, 1 },{ -3, +4, 1 },\r
1296                 { +2, +7, 1 },{ +3, +5, 1 },{ +3, +4, 1 },\r
1297                 { -2, -6, 2 },{ -2, -5, 2 },{ -3, -3, 2 },\r
1298                 { +2, -6, 2 },{ +2, -5, 2 },{ +3, -3, 2 },\r
1299                 { -2, +6, 2 },{ -2, +5, 2 },{ -3, +3, 2 },\r
1300                 { +2, +6, 2 },{ +2, +5, 2 },{ +3, +3, 2 },\r
1301                 { -2, -4, 3 },{ -3, -2, 3 },\r
1302                 { +2, -4, 3 },{ +3, -2, 3 },\r
1303                 { -2, +4, 3 },{ -3, +2, 3 },\r
1304                 { +2, +4, 3 },{ +3, +2, 3 },\r
1305                 { -2, -3, 4 },{ -3, -1, 4 },\r
1306                 { +2, -3, 4 },{ +3, -1, 4 },\r
1307                 { -2, +3, 4 },{ -3, +1, 4 },\r
1308                 { +2, +3, 4 },{ +3, +1, 4 },\r
1309                 { -2, -2, 5 },{ -3, 0, 5 },{ -2, +2, 5 },\r
1310                 { +2, -2, 5 },{ +3, 0, 5 },{ +2, +2, 5 },\r
1311                 { -2, -1, 6 },{ -2, +1, 6 },\r
1312                 { +2, -1, 6 },{ +2, +1, 6 },\r
1313                 { -2, 0, 7 },{ +2, 0, 7 },\r
1314                 { 0, 0, -1 }\r
1315         };\r
1316 \r
1317         POSITION y, x, y1, x1, y2, x2, xval, yval;\r
1318         int i, j;\r
1319 \r
1320         MONRACE_IDX what[16];\r
1321 \r
1322         monster_type align;\r
1323 \r
1324         cave_type *c_ptr;\r
1325 \r
1326         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);\r
1327         vault_aux_type *n_ptr;\r
1328 \r
1329         /* Only in Angband */\r
1330         if (dungeon_type != DUNGEON_ANGBAND) return FALSE;\r
1331 \r
1332         /* No type available */\r
1333         if (cur_pit_type < 0) return FALSE;\r
1334 \r
1335         n_ptr = &pit_types[cur_pit_type];\r
1336 \r
1337         /* Process a preparation function if necessary */\r
1338         if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
1339 \r
1340         /* Prepare allocation table */\r
1341         get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);\r
1342 \r
1343         align.sub_align = SUB_ALIGN_NEUTRAL;\r
1344 \r
1345         /* Pick some monster types */\r
1346         for (i = 0; i < 16; i++)\r
1347         {\r
1348                 MONRACE_IDX r_idx = 0;\r
1349                 int attempts = 100;\r
1350                 monster_race *r_ptr = NULL;\r
1351 \r
1352                 while (attempts--)\r
1353                 {\r
1354                         /* Get a (hard) monster type */\r
1355                         r_idx = get_mon_num(dun_level + 0);\r
1356                         r_ptr = &r_info[r_idx];\r
1357 \r
1358                         /* Decline incorrect alignment */\r
1359                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
1360 \r
1361                         /* Accept this monster */\r
1362                         break;\r
1363                 }\r
1364 \r
1365                 /* Notice failure */\r
1366                 if (!r_idx || !attempts) return FALSE;\r
1367 \r
1368                 /* Note the alignment */\r
1369                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
1370                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
1371 \r
1372                 what[i] = r_idx;\r
1373         }\r
1374 \r
1375         /* Find and reserve some space in the dungeon.  Get center of room. */\r
1376         if (!find_space(&yval, &xval, 13, 25)) return FALSE;\r
1377 \r
1378         /* Large room */\r
1379         y1 = yval - 5;\r
1380         y2 = yval + 5;\r
1381         x1 = xval - 11;\r
1382         x2 = xval + 11;\r
1383 \r
1384         /* Fill with inner walls */\r
1385         for (y = y1 - 1; y <= y2 + 1; y++)\r
1386         {\r
1387                 for (x = x1 - 1; x <= x2 + 1; x++)\r
1388                 {\r
1389                         c_ptr = &cave[y][x];\r
1390                         place_inner_grid(c_ptr);\r
1391                         c_ptr->info |= (CAVE_ROOM);\r
1392                 }\r
1393         }\r
1394 \r
1395         /* Place the floor area 1 */\r
1396         for (x = x1 + 3; x <= x2 - 3; x++)\r
1397         {\r
1398                 c_ptr = &cave[yval - 2][x];\r
1399                 place_floor_grid(c_ptr);\r
1400                 add_cave_info(yval - 2, x, CAVE_ICKY);\r
1401 \r
1402                 c_ptr = &cave[yval + 2][x];\r
1403                 place_floor_grid(c_ptr);\r
1404                 add_cave_info(yval + 2, x, CAVE_ICKY);\r
1405         }\r
1406 \r
1407         /* Place the floor area 2 */\r
1408         for (x = x1 + 5; x <= x2 - 5; x++)\r
1409         {\r
1410                 c_ptr = &cave[yval - 3][x];\r
1411                 place_floor_grid(c_ptr);\r
1412                 add_cave_info(yval - 3, x, CAVE_ICKY);\r
1413 \r
1414                 c_ptr = &cave[yval + 3][x];\r
1415                 place_floor_grid(c_ptr);\r
1416                 add_cave_info(yval + 3, x, CAVE_ICKY);\r
1417         }\r
1418 \r
1419         /* Corridor */\r
1420         for (x = x1; x <= x2; x++)\r
1421         {\r
1422                 c_ptr = &cave[yval][x];\r
1423                 place_floor_grid(c_ptr);\r
1424                 c_ptr = &cave[y1][x];\r
1425                 place_floor_grid(c_ptr);\r
1426                 c_ptr = &cave[y2][x];\r
1427                 place_floor_grid(c_ptr);\r
1428         }\r
1429 \r
1430         /* Place the outer walls */\r
1431         for (y = y1 - 1; y <= y2 + 1; y++)\r
1432         {\r
1433                 c_ptr = &cave[y][x1 - 1];\r
1434                 place_outer_grid(c_ptr);\r
1435                 c_ptr = &cave[y][x2 + 1];\r
1436                 place_outer_grid(c_ptr);\r
1437         }\r
1438         for (x = x1 - 1; x <= x2 + 1; x++)\r
1439         {\r
1440                 c_ptr = &cave[y1 - 1][x];\r
1441                 place_outer_grid(c_ptr);\r
1442                 c_ptr = &cave[y2 + 1][x];\r
1443                 place_outer_grid(c_ptr);\r
1444         }\r
1445 \r
1446         /* Random corridor */\r
1447         if (one_in_(2))\r
1448         {\r
1449                 for (y = y1; y <= yval; y++)\r
1450                 {\r
1451                         place_floor_bold(y, x2);\r
1452                         place_solid_bold(y, x1 - 1);\r
1453                 }\r
1454                 for (y = yval; y <= y2 + 1; y++)\r
1455                 {\r
1456                         place_floor_bold(y, x1);\r
1457                         place_solid_bold(y, x2 + 1);\r
1458                 }\r
1459         }\r
1460         else\r
1461         {\r
1462                 for (y = yval; y <= y2 + 1; y++)\r
1463                 {\r
1464                         place_floor_bold(y, x1);\r
1465                         place_solid_bold(y, x2 + 1);\r
1466                 }\r
1467                 for (y = y1; y <= yval; y++)\r
1468                 {\r
1469                         place_floor_bold(y, x2);\r
1470                         place_solid_bold(y, x1 - 1);\r
1471                 }\r
1472         }\r
1473 \r
1474         /* Place the wall open trap */\r
1475         cave[yval][xval].mimic = cave[yval][xval].feat;\r
1476         cave[yval][xval].feat = feat_trap_open;\r
1477 \r
1478         /* Sort the entries */\r
1479         for (i = 0; i < 16 - 1; i++)\r
1480         {\r
1481                 /* Sort the entries */\r
1482                 for (j = 0; j < 16 - 1; j++)\r
1483                 {\r
1484                         int i1 = j;\r
1485                         int i2 = j + 1;\r
1486 \r
1487                         int p1 = r_info[what[i1]].level;\r
1488                         int p2 = r_info[what[i2]].level;\r
1489 \r
1490                         /* Bubble */\r
1491                         if (p1 > p2)\r
1492                         {\r
1493                                 MONRACE_IDX tmp = what[i1];\r
1494                                 what[i1] = what[i2];\r
1495                                 what[i2] = tmp;\r
1496                         }\r
1497                 }\r
1498         }\r
1499 \r
1500         msg_format_wizard(CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),\r
1501                 n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));\r
1502 \r
1503         /* Select the entries */\r
1504         for (i = 0; i < 8; i++)\r
1505         {\r
1506                 /* Every other entry */\r
1507                 what[i] = what[i * 2];\r
1508 \r
1509                 if (cheat_hear)\r
1510                 {\r
1511                         msg_print(r_name + r_info[what[i]].name);\r
1512                 }\r
1513         }\r
1514 \r
1515         for (i = 0; placing[i][2] >= 0; i++)\r
1516         {\r
1517                 y = yval + placing[i][0];\r
1518                 x = xval + placing[i][1];\r
1519                 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);\r
1520         }\r
1521 \r
1522         return TRUE;\r
1523 }\r
1524 \r