OSDN Git Service

[Refactor] #37353 コメント整理 / Refactor comments.
[hengband/hengband.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         int 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                 /* Done */\r
483                 break;\r
484         }\r
485 \r
486         /* Blue */\r
487         case 1:\r
488         {\r
489                 /* Restrict dragon breath type */\r
490                 vault_aux_dragon_mask4 = RF4_BR_ELEC;\r
491 \r
492                 /* Done */\r
493                 break;\r
494         }\r
495 \r
496         /* Red */\r
497         case 2:\r
498         {\r
499                 /* Restrict dragon breath type */\r
500                 vault_aux_dragon_mask4 = RF4_BR_FIRE;\r
501 \r
502                 /* Done */\r
503                 break;\r
504         }\r
505 \r
506         /* White */\r
507         case 3:\r
508         {\r
509                 /* Restrict dragon breath type */\r
510                 vault_aux_dragon_mask4 = RF4_BR_COLD;\r
511 \r
512                 /* Done */\r
513                 break;\r
514         }\r
515 \r
516         /* Green */\r
517         case 4:\r
518         {\r
519                 /* Restrict dragon breath type */\r
520                 vault_aux_dragon_mask4 = RF4_BR_POIS;\r
521 \r
522                 /* Done */\r
523                 break;\r
524         }\r
525 \r
526         /* Multi-hued */\r
527         default:\r
528         {\r
529                 /* Restrict dragon breath type */\r
530                 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |\r
531                         RF4_BR_FIRE | RF4_BR_COLD |\r
532                         RF4_BR_POIS);\r
533 \r
534                 /* Done */\r
535                 break;\r
536         }\r
537         }\r
538 }\r
539 \r
540 \r
541 /*!\r
542 * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /\r
543 * Helper function for "monster pit (dark elf)"\r
544 * @param r_idx 確認したいモンスター種族ID\r
545 * @return 生成必要条件を満たしているならTRUEを返す。\r
546 */\r
547 static bool vault_aux_dark_elf(MONRACE_IDX r_idx)\r
548 {\r
549         int i;\r
550         static int dark_elf_list[] =\r
551         {\r
552                 MON_D_ELF, MON_D_ELF_MAGE, MON_D_ELF_WARRIOR, MON_D_ELF_PRIEST,\r
553                 MON_D_ELF_LORD, MON_D_ELF_WARLOCK, MON_D_ELF_DRUID, MON_NIGHTBLADE,\r
554                 MON_D_ELF_SORC, MON_D_ELF_SHADE, 0,\r
555         };\r
556 \r
557         /* Validate the monster */\r
558         if (!vault_monster_okay(r_idx)) return FALSE;\r
559 \r
560         /* Require dark elves */\r
561         for (i = 0; dark_elf_list[i]; i++)\r
562                 if (r_idx == dark_elf_list[i]) return TRUE;\r
563 \r
564         /* Assume not */\r
565         return FALSE;\r
566 }\r
567 \r
568 \r
569 /*!\r
570 * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める\r
571 * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ\r
572 * @param allow_flag_mask 生成が許されるpit/nestのビット配列\r
573 * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。\r
574 */\r
575 static int pick_vault_type(vault_aux_type *l_ptr, BIT_FLAGS16 allow_flag_mask)\r
576 {\r
577         int tmp, total, count;\r
578 \r
579         vault_aux_type *n_ptr;\r
580 \r
581         /* Calculate the total possibilities */\r
582         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)\r
583         {\r
584                 /* Note end */\r
585                 if (!n_ptr->name) break;\r
586 \r
587                 /* Ignore excessive depth */\r
588                 if (n_ptr->level > dun_level) continue;\r
589 \r
590                 /* Not matched with pit/nest flag */\r
591                 if (!(allow_flag_mask & (1L << count))) continue;\r
592 \r
593                 /* Count this possibility */\r
594                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);\r
595         }\r
596 \r
597         /* Pick a random type */\r
598         tmp = randint0(total);\r
599 \r
600         /* Find this type */\r
601         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)\r
602         {\r
603                 /* Note end */\r
604                 if (!n_ptr->name) break;\r
605 \r
606                 /* Ignore excessive depth */\r
607                 if (n_ptr->level > dun_level) continue;\r
608 \r
609                 /* Not matched with pit/nest flag */\r
610                 if (!(allow_flag_mask & (1L << count))) continue;\r
611 \r
612                 /* Count this possibility */\r
613                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);\r
614 \r
615                 /* Found the type */\r
616                 if (tmp < total) break;\r
617         }\r
618 \r
619         return n_ptr->name ? count : -1;\r
620 }\r
621 \r
622 /*!\r
623 * @brief デバッグ時に生成されたpit/nestの型を出力する処理\r
624 * @param type pit/nestの型ID\r
625 * @param nest TRUEならばnest、FALSEならばpit\r
626 * @return デバッグ表示文字列の参照ポインタ\r
627 * @details\r
628 * Hack -- Get the string describing subtype of pit/nest\r
629 * Determined in prepare function (some pit/nest only)\r
630 */\r
631 static cptr pit_subtype_string(int type, bool nest)\r
632 {\r
633         static char inner_buf[256] = "";\r
634 \r
635         inner_buf[0] = '\0'; /* Init string */\r
636 \r
637         if (nest) /* Nests */\r
638         {\r
639                 switch (type)\r
640                 {\r
641                 case NEST_TYPE_CLONE:\r
642                         sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);\r
643                         break;\r
644                 case NEST_TYPE_SYMBOL_GOOD:\r
645                 case NEST_TYPE_SYMBOL_EVIL:\r
646                         sprintf(inner_buf, "(%c)", vault_aux_char);\r
647                         break;\r
648                 }\r
649         }\r
650         else /* Pits */\r
651         {\r
652                 switch (type)\r
653                 {\r
654                 case PIT_TYPE_SYMBOL_GOOD:\r
655                 case PIT_TYPE_SYMBOL_EVIL:\r
656                         sprintf(inner_buf, "(%c)", vault_aux_char);\r
657                         break;\r
658                 case PIT_TYPE_DRAGON:\r
659                         switch (vault_aux_dragon_mask4)\r
660                         {\r
661                                 case RF4_BR_ACID: strcpy(inner_buf, _("(酸)", "(acid)"));   break;\r
662                                 case RF4_BR_ELEC: strcpy(inner_buf, _("(稲妻)", "(lightning)")); break;\r
663                                 case RF4_BR_FIRE: strcpy(inner_buf, _("(火炎)", "(fire)")); break;\r
664                                 case RF4_BR_COLD: strcpy(inner_buf, _("(冷気)", "(frost)")); break;\r
665                                 case RF4_BR_POIS: strcpy(inner_buf, _("(毒)", "(poison)"));   break;\r
666                                 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS) :\r
667                                         strcpy(inner_buf, _("(万色)", "(multi-hued)")); break;\r
668                                 default: strcpy(inner_buf, _("(未定義)", "(undefined)")); break;\r
669                         }\r
670                         break;\r
671                 }\r
672         }\r
673 \r
674         return inner_buf;\r
675 }\r
676 \r
677 \r
678 \r
679 \r
680 \r
681 /*\r
682 *! @brief nestのモンスターリストをソートするための関数 /\r
683 *  Comp function for sorting nest monster information\r
684 *  @param u ソート処理対象配列ポインタ\r
685 *  @param v 未使用\r
686 *  @param a 比較対象参照ID1\r
687 *  @param b 比較対象参照ID2\r
688 */\r
689 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)\r
690 {\r
691         nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;\r
692         MONSTER_IDX w1 = nest_mon_info[a].r_idx;\r
693         MONSTER_IDX w2 = nest_mon_info[b].r_idx;\r
694         monster_race *r1_ptr = &r_info[w1];\r
695         monster_race *r2_ptr = &r_info[w2];\r
696         int z1, z2;\r
697 \r
698         /* Unused */\r
699         (void)v;\r
700 \r
701         /* Extract used info */\r
702         z1 = nest_mon_info[a].used;\r
703         z2 = nest_mon_info[b].used;\r
704 \r
705         /* Compare used status */\r
706         if (z1 < z2) return FALSE;\r
707         if (z1 > z2) return TRUE;\r
708 \r
709         /* Compare levels */\r
710         if (r1_ptr->level < r2_ptr->level) return TRUE;\r
711         if (r1_ptr->level > r2_ptr->level) return FALSE;\r
712 \r
713         /* Compare experience */\r
714         if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;\r
715         if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;\r
716 \r
717         /* Compare indexes */\r
718         return w1 <= w2;\r
719 }\r
720 \r
721 /*!\r
722 * @brief nestのモンスターリストをスワップするための関数 /\r
723 * Swap function for sorting nest monster information\r
724 * @param u スワップ処理対象配列ポインタ\r
725 * @param v 未使用\r
726 * @param a スワップ対象参照ID1\r
727 * @param b スワップ対象参照ID2\r
728 */\r
729 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)\r
730 {\r
731         nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;\r
732         nest_mon_info_type holder;\r
733 \r
734         /* Unused */\r
735         (void)v;\r
736 \r
737         /* Swap */\r
738         holder = nest_mon_info[a];\r
739         nest_mon_info[a] = nest_mon_info[b];\r
740         nest_mon_info[b] = holder;\r
741 }\r
742 \r
743 \r
744 \r
745 /*!nest情報テーブル*/\r
746 static vault_aux_type nest_types[] =\r
747 {\r
748         { _("クローン", "clone"),      vault_aux_clone,    vault_prep_clone,   5, 3 },\r
749         { _("ゼリー", "jelly"),        vault_aux_jelly,    NULL,               5, 6 },\r
750         { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 25, 2 },\r
751         { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 25, 2 },\r
752         { _("ミミック", "mimic"),      vault_aux_mimic,    NULL,              30, 4 },\r
753         { _("狂気", "lovecraftian"),   vault_aux_cthulhu,  NULL,              70, 2 },\r
754         { _("犬小屋", "kennel"),       vault_aux_kennel,   NULL,              45, 4 },\r
755         { _("動物園", "animal"),       vault_aux_animal,   NULL,              35, 5 },\r
756         { _("教会", "chapel"),         vault_aux_chapel_g, NULL,              75, 4 },\r
757         { _("アンデッド", "undead"),   vault_aux_undead,   NULL,              75, 5 },\r
758         { NULL,           NULL,               NULL,               0, 0 },\r
759 };\r
760 \r
761 /*!pit情報テーブル*/\r
762 static vault_aux_type pit_types[] =\r
763 {\r
764         { _("オーク", "orc"),            vault_aux_orc,      NULL,               5, 6 },\r
765         { _("トロル", "troll"),          vault_aux_troll,    NULL,              20, 6 },\r
766         { _("ジャイアント", "giant"),    vault_aux_giant,    NULL,              50, 6 },\r
767         { _("狂気", "lovecraftian"),     vault_aux_cthulhu,  NULL,              80, 2 },\r
768         { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 70, 1 },\r
769         { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 70, 1 },\r
770         { _("教会", "chapel"),           vault_aux_chapel_g, NULL,              65, 2 },\r
771         { _("ドラゴン", "dragon"),       vault_aux_dragon,   vault_prep_dragon, 70, 6 },\r
772         { _("デーモン", "demon"),        vault_aux_demon,    NULL,              80, 6 },\r
773         { _("ダークエルフ", "dark elf"), vault_aux_dark_elf, NULL,              45, 4 },\r
774         { NULL,           NULL,               NULL,               0, 0 },\r
775 };\r
776 \r
777 \r
778 \r
779 \r
780 /*!\r
781 * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests\r
782 * @return なし\r
783 * @details\r
784 * A monster nest is a "big" room, with an "inner" room, containing\n\r
785 * a "collection" of monsters of a given type strewn about the room.\n\r
786 *\n\r
787 * The monsters are chosen from a set of 64 randomly selected monster\n\r
788 * races, to allow the nest creation to fail instead of having "holes".\n\r
789 *\n\r
790 * Note the use of the "get_mon_num_prep()" function, and the special\n\r
791 * "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
792 * allocation table" in such a way as to optimize the selection of\n\r
793 * "appropriate" non-unique monsters for the nest.\n\r
794 *\n\r
795 * Note that the "get_mon_num()" function may (rarely) fail, in which\n\r
796 * case the nest will be empty.\n\r
797 *\n\r
798 * Note that "monster nests" will never contain "unique" monsters.\n\r
799 */\r
800 bool build_type5(void)\r
801 {\r
802         POSITION y, x, y1, x1, y2, x2, xval, yval;\r
803         int i;\r
804         nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];\r
805 \r
806         monster_type align;\r
807 \r
808         cave_type *c_ptr;\r
809 \r
810         int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);\r
811         vault_aux_type *n_ptr;\r
812 \r
813         /* No type available */\r
814         if (cur_nest_type < 0) return FALSE;\r
815 \r
816         n_ptr = &nest_types[cur_nest_type];\r
817 \r
818         /* Process a preparation function if necessary */\r
819         if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
820 \r
821         /* Prepare allocation table */\r
822         get_mon_num_prep(n_ptr->hook_func, NULL);\r
823 \r
824         align.sub_align = SUB_ALIGN_NEUTRAL;\r
825 \r
826         /* Pick some monster types */\r
827         for (i = 0; i < NUM_NEST_MON_TYPE; i++)\r
828         {\r
829                 MONRACE_IDX r_idx = 0;\r
830                 int attempts = 100;\r
831                 monster_race *r_ptr = NULL;\r
832 \r
833                 while (attempts--)\r
834                 {\r
835                         /* Get a (hard) monster type */\r
836                         r_idx = get_mon_num(dun_level + 11);\r
837                         r_ptr = &r_info[r_idx];\r
838 \r
839                         /* Decline incorrect alignment */\r
840                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
841 \r
842                         /* Accept this monster */\r
843                         break;\r
844                 }\r
845 \r
846                 /* Notice failure */\r
847                 if (!r_idx || !attempts) return FALSE;\r
848 \r
849                 /* Note the alignment */\r
850                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
851                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
852 \r
853                 nest_mon_info[i].r_idx = (s16b)r_idx;\r
854                 nest_mon_info[i].used = FALSE;\r
855         }\r
856 \r
857         /* Find and reserve some space in the dungeon.  Get center of room. */\r
858         if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
859 \r
860         /* Large room */\r
861         y1 = yval - 4;\r
862         y2 = yval + 4;\r
863         x1 = xval - 11;\r
864         x2 = xval + 11;\r
865 \r
866         /* Place the floor area */\r
867         for (y = y1 - 1; y <= y2 + 1; y++)\r
868         {\r
869                 for (x = x1 - 1; x <= x2 + 1; x++)\r
870                 {\r
871                         c_ptr = &cave[y][x];\r
872                         place_floor_grid(c_ptr);\r
873                         c_ptr->info |= (CAVE_ROOM);\r
874                 }\r
875         }\r
876 \r
877         /* Place the outer walls */\r
878         for (y = y1 - 1; y <= y2 + 1; y++)\r
879         {\r
880                 c_ptr = &cave[y][x1 - 1];\r
881                 place_outer_grid(c_ptr);\r
882                 c_ptr = &cave[y][x2 + 1];\r
883                 place_outer_grid(c_ptr);\r
884         }\r
885         for (x = x1 - 1; x <= x2 + 1; x++)\r
886         {\r
887                 c_ptr = &cave[y1 - 1][x];\r
888                 place_outer_grid(c_ptr);\r
889                 c_ptr = &cave[y2 + 1][x];\r
890                 place_outer_grid(c_ptr);\r
891         }\r
892 \r
893 \r
894         /* Advance to the center room */\r
895         y1 = y1 + 2;\r
896         y2 = y2 - 2;\r
897         x1 = x1 + 2;\r
898         x2 = x2 - 2;\r
899 \r
900         /* The inner walls */\r
901         for (y = y1 - 1; y <= y2 + 1; y++)\r
902         {\r
903                 c_ptr = &cave[y][x1 - 1];\r
904                 place_inner_grid(c_ptr);\r
905                 c_ptr = &cave[y][x2 + 1];\r
906                 place_inner_grid(c_ptr);\r
907         }\r
908 \r
909         for (x = x1 - 1; x <= x2 + 1; x++)\r
910         {\r
911                 c_ptr = &cave[y1 - 1][x];\r
912                 place_inner_grid(c_ptr);\r
913                 c_ptr = &cave[y2 + 1][x];\r
914                 place_inner_grid(c_ptr);\r
915         }\r
916         for (y = y1; y <= y2; y++)\r
917         {\r
918                 for (x = x1; x <= x2; x++)\r
919                 {\r
920                         add_cave_info(y, x, CAVE_ICKY);\r
921                 }\r
922         }\r
923 \r
924         /* Place a secret door */\r
925         switch (randint1(4))\r
926         {\r
927         case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
928         case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
929         case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
930         case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
931         }\r
932 \r
933         msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));\r
934 \r
935         /* Place some monsters */\r
936         for (y = yval - 2; y <= yval + 2; y++)\r
937         {\r
938                 for (x = xval - 9; x <= xval + 9; x++)\r
939                 {\r
940                         MONRACE_IDX r_idx;\r
941 \r
942                         i = randint0(NUM_NEST_MON_TYPE);\r
943                         r_idx = nest_mon_info[i].r_idx;\r
944 \r
945                         /* Place that "random" monster (no groups) */\r
946                         (void)place_monster_aux(0, y, x, r_idx, 0L);\r
947 \r
948                         nest_mon_info[i].used = TRUE;\r
949                 }\r
950         }\r
951 \r
952         if (cheat_room)\r
953         {\r
954                 ang_sort_comp = ang_sort_comp_nest_mon_info;\r
955                 ang_sort_swap = ang_sort_swap_nest_mon_info;\r
956                 ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);\r
957 \r
958                 /* Dump the entries (prevent multi-printing) */\r
959                 for (i = 0; i < NUM_NEST_MON_TYPE; i++)\r
960                 {\r
961                         if (!nest_mon_info[i].used) break;\r
962                         for (; i < NUM_NEST_MON_TYPE - 1; i++)\r
963                         {\r
964                                 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;\r
965                                 if (!nest_mon_info[i + 1].used) break;\r
966                         }\r
967                         msg_format_wizard(CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);\r
968                 }\r
969         }\r
970 \r
971         return TRUE;\r
972 }\r
973 \r
974 \r
975 /*!\r
976 * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits\r
977 * @return なし\r
978 * @details\r
979 * A monster pit is a "big" room, with an "inner" room, containing\n\r
980 * a "collection" of monsters of a given type organized in the room.\n\r
981 *\n\r
982 * The inside room in a monster pit appears as shown below, where the\n\r
983 * actual monsters in each location depend on the type of the pit\n\r
984 *\n\r
985 *   XXXXXXXXXXXXXXXXXXXXX\n\r
986 *   X0000000000000000000X\n\r
987 *   X0112233455543322110X\n\r
988 *   X0112233467643322110X\n\r
989 *   X0112233455543322110X\n\r
990 *   X0000000000000000000X\n\r
991 *   XXXXXXXXXXXXXXXXXXXXX\n\r
992 *\n\r
993 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n\r
994 * to request 16 "appropriate" monsters, sorting them by level, and using\n\r
995 * the "even" entries in this sorted list for the contents of the pit.\n\r
996 *\n\r
997 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n\r
998 * which is handled by requiring a specific "breath" attack for all of the\n\r
999 * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n\r
1000 * be present in many of the dragon pits, if they have the proper breath.\n\r
1001 *\n\r
1002 * Note the use of the "get_mon_num_prep()" function, and the special\n\r
1003 * "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
1004 * allocation table" in such a way as to optimize the selection of\n\r
1005 * "appropriate" non-unique monsters for the pit.\n\r
1006 *\n\r
1007 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n\r
1008 * the pit will be empty.\n\r
1009 *\n\r
1010 * Note that "monster pits" will never contain "unique" monsters.\n\r
1011 */\r
1012 bool build_type6(void)\r
1013 {\r
1014         POSITION y, x, y1, x1, y2, x2, xval, yval;\r
1015         int i, j;\r
1016 \r
1017         MONRACE_IDX what[16];\r
1018 \r
1019         monster_type align;\r
1020 \r
1021         cave_type *c_ptr;\r
1022 \r
1023         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);\r
1024         vault_aux_type *n_ptr;\r
1025 \r
1026         /* No type available */\r
1027         if (cur_pit_type < 0) return FALSE;\r
1028 \r
1029         n_ptr = &pit_types[cur_pit_type];\r
1030 \r
1031         /* Process a preparation function if necessary */\r
1032         if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
1033 \r
1034         /* Prepare allocation table */\r
1035         get_mon_num_prep(n_ptr->hook_func, NULL);\r
1036 \r
1037         align.sub_align = SUB_ALIGN_NEUTRAL;\r
1038 \r
1039         /* Pick some monster types */\r
1040         for (i = 0; i < 16; i++)\r
1041         {\r
1042                 MONRACE_IDX r_idx = 0;\r
1043                 int attempts = 100;\r
1044                 monster_race *r_ptr = NULL;\r
1045 \r
1046                 while (attempts--)\r
1047                 {\r
1048                         /* Get a (hard) monster type */\r
1049                         r_idx = get_mon_num(dun_level + 11);\r
1050                         r_ptr = &r_info[r_idx];\r
1051 \r
1052                         /* Decline incorrect alignment */\r
1053                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
1054 \r
1055                         /* Accept this monster */\r
1056                         break;\r
1057                 }\r
1058 \r
1059                 /* Notice failure */\r
1060                 if (!r_idx || !attempts) return FALSE;\r
1061 \r
1062                 /* Note the alignment */\r
1063                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
1064                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
1065 \r
1066                 what[i] = r_idx;\r
1067         }\r
1068 \r
1069         /* Find and reserve some space in the dungeon.  Get center of room. */\r
1070         if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
1071 \r
1072         /* Large room */\r
1073         y1 = yval - 4;\r
1074         y2 = yval + 4;\r
1075         x1 = xval - 11;\r
1076         x2 = xval + 11;\r
1077 \r
1078         /* Place the floor area */\r
1079         for (y = y1 - 1; y <= y2 + 1; y++)\r
1080         {\r
1081                 for (x = x1 - 1; x <= x2 + 1; x++)\r
1082                 {\r
1083                         c_ptr = &cave[y][x];\r
1084                         place_floor_grid(c_ptr);\r
1085                         c_ptr->info |= (CAVE_ROOM);\r
1086                 }\r
1087         }\r
1088 \r
1089         /* Place the outer walls */\r
1090         for (y = y1 - 1; y <= y2 + 1; y++)\r
1091         {\r
1092                 c_ptr = &cave[y][x1 - 1];\r
1093                 place_outer_grid(c_ptr);\r
1094                 c_ptr = &cave[y][x2 + 1];\r
1095                 place_outer_grid(c_ptr);\r
1096         }\r
1097         for (x = x1 - 1; x <= x2 + 1; x++)\r
1098         {\r
1099                 c_ptr = &cave[y1 - 1][x];\r
1100                 place_outer_grid(c_ptr);\r
1101                 c_ptr = &cave[y2 + 1][x];\r
1102                 place_outer_grid(c_ptr);\r
1103         }\r
1104 \r
1105         /* Advance to the center room */\r
1106         y1 = y1 + 2;\r
1107         y2 = y2 - 2;\r
1108         x1 = x1 + 2;\r
1109         x2 = x2 - 2;\r
1110 \r
1111         /* The inner walls */\r
1112         for (y = y1 - 1; y <= y2 + 1; y++)\r
1113         {\r
1114                 c_ptr = &cave[y][x1 - 1];\r
1115                 place_inner_grid(c_ptr);\r
1116                 c_ptr = &cave[y][x2 + 1];\r
1117                 place_inner_grid(c_ptr);\r
1118         }\r
1119         for (x = x1 - 1; x <= x2 + 1; x++)\r
1120         {\r
1121                 c_ptr = &cave[y1 - 1][x];\r
1122                 place_inner_grid(c_ptr);\r
1123                 c_ptr = &cave[y2 + 1][x];\r
1124                 place_inner_grid(c_ptr);\r
1125         }\r
1126         for (y = y1; y <= y2; y++)\r
1127         {\r
1128                 for (x = x1; x <= x2; x++)\r
1129                 {\r
1130                         add_cave_info(y, x, CAVE_ICKY);\r
1131                 }\r
1132         }\r
1133 \r
1134         /* Place a secret door */\r
1135         switch (randint1(4))\r
1136         {\r
1137         case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
1138         case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
1139         case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
1140         case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
1141         }\r
1142 \r
1143         /* Sort the entries */\r
1144         for (i = 0; i < 16 - 1; i++)\r
1145         {\r
1146                 /* Sort the entries */\r
1147                 for (j = 0; j < 16 - 1; j++)\r
1148                 {\r
1149                         int i1 = j;\r
1150                         int i2 = j + 1;\r
1151 \r
1152                         int p1 = r_info[what[i1]].level;\r
1153                         int p2 = r_info[what[i2]].level;\r
1154 \r
1155                         /* Bubble */\r
1156                         if (p1 > p2)\r
1157                         {\r
1158                                 MONRACE_IDX tmp = what[i1];\r
1159                                 what[i1] = what[i2];\r
1160                                 what[i2] = tmp;\r
1161                         }\r
1162                 }\r
1163         }\r
1164 \r
1165         msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));\r
1166 \r
1167         /* Select the entries */\r
1168         for (i = 0; i < 8; i++)\r
1169         {\r
1170                 /* Every other entry */\r
1171                 what[i] = what[i * 2];\r
1172                 msg_format_wizard(CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);\r
1173         }\r
1174 \r
1175         /* Top and bottom rows */\r
1176         for (x = xval - 9; x <= xval + 9; x++)\r
1177         {\r
1178                 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);\r
1179                 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);\r
1180         }\r
1181 \r
1182         /* Middle columns */\r
1183         for (y = yval - 1; y <= yval + 1; y++)\r
1184         {\r
1185                 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);\r
1186                 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);\r
1187 \r
1188                 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);\r
1189                 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);\r
1190 \r
1191                 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);\r
1192                 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);\r
1193 \r
1194                 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);\r
1195                 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);\r
1196 \r
1197                 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);\r
1198                 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);\r
1199 \r
1200                 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);\r
1201                 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);\r
1202 \r
1203                 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);\r
1204                 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);\r
1205 \r
1206                 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);\r
1207                 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);\r
1208         }\r
1209 \r
1210         /* Above/Below the center monster */\r
1211         for (x = xval - 1; x <= xval + 1; x++)\r
1212         {\r
1213                 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);\r
1214                 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);\r
1215         }\r
1216 \r
1217         /* Next to the center monster */\r
1218         place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);\r
1219         place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);\r
1220 \r
1221         /* Center monster */\r
1222         place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);\r
1223 \r
1224         return TRUE;\r
1225 }\r
1226 \r
1227 \r
1228 \r
1229 /*\r
1230 * Helper function for "trapped monster pit"\r
1231 */\r
1232 static bool vault_aux_trapped_pit(MONRACE_IDX r_idx)\r
1233 {\r
1234         monster_race *r_ptr = &r_info[r_idx];\r
1235 \r
1236         /* Validate the monster */\r
1237         if (!vault_monster_okay(r_idx)) return (FALSE);\r
1238 \r
1239         /* No wall passing monster */\r
1240         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);\r
1241 \r
1242         /* Okay */\r
1243         return (TRUE);\r
1244 }\r
1245 \r
1246 \r
1247 /*!\r
1248 * @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits\r
1249 * @return なし\r
1250 * @details\r
1251 * A trapped monster pit is a "big" room with a straight corridor in\n\r
1252 * which wall opening traps are placed, and with two "inner" rooms\n\r
1253 * containing a "collection" of monsters of a given type organized in\n\r
1254 * the room.\n\r
1255 *\n\r
1256 * The trapped monster pit appears as shown below, where the actual\n\r
1257 * monsters in each location depend on the type of the pit\n\r
1258 *\n\r
1259 *  XXXXXXXXXXXXXXXXXXXXXXXXX\n\r
1260 *  X                       X\n\r
1261 *  XXXXXXXXXXXXXXXXXXXXXXX X\n\r
1262 *  XXXXX001123454321100XXX X\n\r
1263 *  XXX0012234567654322100X X\n\r
1264 *  XXXXXXXXXXXXXXXXXXXXXXX X\n\r
1265 *  X           ^           X\n\r
1266 *  X XXXXXXXXXXXXXXXXXXXXXXX\n\r
1267 *  X X0012234567654322100XXX\n\r
1268 *  X XXX001123454321100XXXXX\n\r
1269 *  X XXXXXXXXXXXXXXXXXXXXXXX\n\r
1270 *  X                       X\n\r
1271 *  XXXXXXXXXXXXXXXXXXXXXXXXX\n\r
1272 *\n\r
1273 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n\r
1274 * to request 16 "appropriate" monsters, sorting them by level, and using\n\r
1275 * the "even" entries in this sorted list for the contents of the pit.\n\r
1276 *\n\r
1277 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n\r
1278 * which is handled by requiring a specific "breath" attack for all of the\n\r
1279 * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n\r
1280 * be present in many of the dragon pits, if they have the proper breath.\n\r
1281 *\n\r
1282 * Note the use of the "get_mon_num_prep()" function, and the special\n\r
1283 * "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
1284 * allocation table" in such a way as to optimize the selection of\n\r
1285 * "appropriate" non-unique monsters for the pit.\n\r
1286 *\n\r
1287 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n\r
1288 * the pit will be empty.\n\r
1289 *\n\r
1290 * Note that "monster pits" will never contain "unique" monsters.\n\r
1291 */\r
1292 bool build_type13(void)\r
1293 {\r
1294         static int placing[][3] = {\r
1295                 { -2, -9, 0 },{ -2, -8, 0 },{ -3, -7, 0 },{ -3, -6, 0 },\r
1296                 { +2, -9, 0 },{ +2, -8, 0 },{ +3, -7, 0 },{ +3, -6, 0 },\r
1297                 { -2, +9, 0 },{ -2, +8, 0 },{ -3, +7, 0 },{ -3, +6, 0 },\r
1298                 { +2, +9, 0 },{ +2, +8, 0 },{ +3, +7, 0 },{ +3, +6, 0 },\r
1299                 { -2, -7, 1 },{ -3, -5, 1 },{ -3, -4, 1 },\r
1300                 { +2, -7, 1 },{ +3, -5, 1 },{ +3, -4, 1 },\r
1301                 { -2, +7, 1 },{ -3, +5, 1 },{ -3, +4, 1 },\r
1302                 { +2, +7, 1 },{ +3, +5, 1 },{ +3, +4, 1 },\r
1303                 { -2, -6, 2 },{ -2, -5, 2 },{ -3, -3, 2 },\r
1304                 { +2, -6, 2 },{ +2, -5, 2 },{ +3, -3, 2 },\r
1305                 { -2, +6, 2 },{ -2, +5, 2 },{ -3, +3, 2 },\r
1306                 { +2, +6, 2 },{ +2, +5, 2 },{ +3, +3, 2 },\r
1307                 { -2, -4, 3 },{ -3, -2, 3 },\r
1308                 { +2, -4, 3 },{ +3, -2, 3 },\r
1309                 { -2, +4, 3 },{ -3, +2, 3 },\r
1310                 { +2, +4, 3 },{ +3, +2, 3 },\r
1311                 { -2, -3, 4 },{ -3, -1, 4 },\r
1312                 { +2, -3, 4 },{ +3, -1, 4 },\r
1313                 { -2, +3, 4 },{ -3, +1, 4 },\r
1314                 { +2, +3, 4 },{ +3, +1, 4 },\r
1315                 { -2, -2, 5 },{ -3, 0, 5 },{ -2, +2, 5 },\r
1316                 { +2, -2, 5 },{ +3, 0, 5 },{ +2, +2, 5 },\r
1317                 { -2, -1, 6 },{ -2, +1, 6 },\r
1318                 { +2, -1, 6 },{ +2, +1, 6 },\r
1319                 { -2, 0, 7 },{ +2, 0, 7 },\r
1320                 { 0, 0, -1 }\r
1321         };\r
1322 \r
1323         POSITION y, x, y1, x1, y2, x2, xval, yval;\r
1324         int i, j;\r
1325 \r
1326         MONRACE_IDX what[16];\r
1327 \r
1328         monster_type align;\r
1329 \r
1330         cave_type *c_ptr;\r
1331 \r
1332         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);\r
1333         vault_aux_type *n_ptr;\r
1334 \r
1335         /* Only in Angband */\r
1336         if (dungeon_type != DUNGEON_ANGBAND) return FALSE;\r
1337 \r
1338         /* No type available */\r
1339         if (cur_pit_type < 0) return FALSE;\r
1340 \r
1341         n_ptr = &pit_types[cur_pit_type];\r
1342 \r
1343         /* Process a preparation function if necessary */\r
1344         if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
1345 \r
1346         /* Prepare allocation table */\r
1347         get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);\r
1348 \r
1349         align.sub_align = SUB_ALIGN_NEUTRAL;\r
1350 \r
1351         /* Pick some monster types */\r
1352         for (i = 0; i < 16; i++)\r
1353         {\r
1354                 MONRACE_IDX r_idx = 0;\r
1355                 int attempts = 100;\r
1356                 monster_race *r_ptr = NULL;\r
1357 \r
1358                 while (attempts--)\r
1359                 {\r
1360                         /* Get a (hard) monster type */\r
1361                         r_idx = get_mon_num(dun_level + 0);\r
1362                         r_ptr = &r_info[r_idx];\r
1363 \r
1364                         /* Decline incorrect alignment */\r
1365                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
1366 \r
1367                         /* Accept this monster */\r
1368                         break;\r
1369                 }\r
1370 \r
1371                 /* Notice failure */\r
1372                 if (!r_idx || !attempts) return FALSE;\r
1373 \r
1374                 /* Note the alignment */\r
1375                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
1376                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
1377 \r
1378                 what[i] = r_idx;\r
1379         }\r
1380 \r
1381         /* Find and reserve some space in the dungeon.  Get center of room. */\r
1382         if (!find_space(&yval, &xval, 13, 25)) return FALSE;\r
1383 \r
1384         /* Large room */\r
1385         y1 = yval - 5;\r
1386         y2 = yval + 5;\r
1387         x1 = xval - 11;\r
1388         x2 = xval + 11;\r
1389 \r
1390         /* Fill with inner walls */\r
1391         for (y = y1 - 1; y <= y2 + 1; y++)\r
1392         {\r
1393                 for (x = x1 - 1; x <= x2 + 1; x++)\r
1394                 {\r
1395                         c_ptr = &cave[y][x];\r
1396                         place_inner_grid(c_ptr);\r
1397                         c_ptr->info |= (CAVE_ROOM);\r
1398                 }\r
1399         }\r
1400 \r
1401         /* Place the floor area 1 */\r
1402         for (x = x1 + 3; x <= x2 - 3; x++)\r
1403         {\r
1404                 c_ptr = &cave[yval - 2][x];\r
1405                 place_floor_grid(c_ptr);\r
1406                 add_cave_info(yval - 2, x, CAVE_ICKY);\r
1407 \r
1408                 c_ptr = &cave[yval + 2][x];\r
1409                 place_floor_grid(c_ptr);\r
1410                 add_cave_info(yval + 2, x, CAVE_ICKY);\r
1411         }\r
1412 \r
1413         /* Place the floor area 2 */\r
1414         for (x = x1 + 5; x <= x2 - 5; x++)\r
1415         {\r
1416                 c_ptr = &cave[yval - 3][x];\r
1417                 place_floor_grid(c_ptr);\r
1418                 add_cave_info(yval - 3, x, CAVE_ICKY);\r
1419 \r
1420                 c_ptr = &cave[yval + 3][x];\r
1421                 place_floor_grid(c_ptr);\r
1422                 add_cave_info(yval + 3, x, CAVE_ICKY);\r
1423         }\r
1424 \r
1425         /* Corridor */\r
1426         for (x = x1; x <= x2; x++)\r
1427         {\r
1428                 c_ptr = &cave[yval][x];\r
1429                 place_floor_grid(c_ptr);\r
1430                 c_ptr = &cave[y1][x];\r
1431                 place_floor_grid(c_ptr);\r
1432                 c_ptr = &cave[y2][x];\r
1433                 place_floor_grid(c_ptr);\r
1434         }\r
1435 \r
1436         /* Place the outer walls */\r
1437         for (y = y1 - 1; y <= y2 + 1; y++)\r
1438         {\r
1439                 c_ptr = &cave[y][x1 - 1];\r
1440                 place_outer_grid(c_ptr);\r
1441                 c_ptr = &cave[y][x2 + 1];\r
1442                 place_outer_grid(c_ptr);\r
1443         }\r
1444         for (x = x1 - 1; x <= x2 + 1; x++)\r
1445         {\r
1446                 c_ptr = &cave[y1 - 1][x];\r
1447                 place_outer_grid(c_ptr);\r
1448                 c_ptr = &cave[y2 + 1][x];\r
1449                 place_outer_grid(c_ptr);\r
1450         }\r
1451 \r
1452         /* Random corridor */\r
1453         if (one_in_(2))\r
1454         {\r
1455                 for (y = y1; y <= yval; y++)\r
1456                 {\r
1457                         place_floor_bold(y, x2);\r
1458                         place_solid_bold(y, x1 - 1);\r
1459                 }\r
1460                 for (y = yval; y <= y2 + 1; y++)\r
1461                 {\r
1462                         place_floor_bold(y, x1);\r
1463                         place_solid_bold(y, x2 + 1);\r
1464                 }\r
1465         }\r
1466         else\r
1467         {\r
1468                 for (y = yval; y <= y2 + 1; y++)\r
1469                 {\r
1470                         place_floor_bold(y, x1);\r
1471                         place_solid_bold(y, x2 + 1);\r
1472                 }\r
1473                 for (y = y1; y <= yval; y++)\r
1474                 {\r
1475                         place_floor_bold(y, x2);\r
1476                         place_solid_bold(y, x1 - 1);\r
1477                 }\r
1478         }\r
1479 \r
1480         /* Place the wall open trap */\r
1481         cave[yval][xval].mimic = cave[yval][xval].feat;\r
1482         cave[yval][xval].feat = feat_trap_open;\r
1483 \r
1484         /* Sort the entries */\r
1485         for (i = 0; i < 16 - 1; i++)\r
1486         {\r
1487                 /* Sort the entries */\r
1488                 for (j = 0; j < 16 - 1; j++)\r
1489                 {\r
1490                         int i1 = j;\r
1491                         int i2 = j + 1;\r
1492 \r
1493                         int p1 = r_info[what[i1]].level;\r
1494                         int p2 = r_info[what[i2]].level;\r
1495 \r
1496                         /* Bubble */\r
1497                         if (p1 > p2)\r
1498                         {\r
1499                                 MONRACE_IDX tmp = what[i1];\r
1500                                 what[i1] = what[i2];\r
1501                                 what[i2] = tmp;\r
1502                         }\r
1503                 }\r
1504         }\r
1505 \r
1506         msg_format_wizard(CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),\r
1507                 n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));\r
1508 \r
1509         /* Select the entries */\r
1510         for (i = 0; i < 8; i++)\r
1511         {\r
1512                 /* Every other entry */\r
1513                 what[i] = what[i * 2];\r
1514 \r
1515                 if (cheat_hear)\r
1516                 {\r
1517                         msg_print(r_name + r_info[what[i]].name);\r
1518                 }\r
1519         }\r
1520 \r
1521         for (i = 0; placing[i][2] >= 0; i++)\r
1522         {\r
1523                 y = yval + placing[i][0];\r
1524                 x = xval + placing[i][1];\r
1525                 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);\r
1526         }\r
1527 \r
1528         return TRUE;\r
1529 }\r
1530 \r