OSDN Git Service

[Refactor] #37353 object2~trap間整理。 / Refactor between object2 and trap.
[hengbandforosx/hengbandosx.git] / src / rooms.c
1 /*!
2  * @file rooms.c
3  * @brief ダンジョンフロアの部屋生成処理 / make rooms. Used by generate.c when creating dungeons.
4  * @date 2014/01/06
5  * @author
6  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7  * This software may be copied and distributed for educational, research,\n
8  * and not for profit purposes provided that this copyright and statement\n
9  * are included in all such copies.  Other copyrights may also apply.\n
10  * 2014 Deskull rearranged comment for Doxygen. \n
11  * @details
12  * Room building routines.\n
13  *\n
14  * Room types:\n
15  *   1 -- normal\n
16  *   2 -- overlapping\n
17  *   3 -- cross shaped\n
18  *   4 -- large room with features\n
19  *   5 -- monster nests\n
20  *   6 -- monster pits\n
21  *   7 -- simple vaults\n
22  *   8 -- greater vaults\n
23  *   9 -- fractal caves\n
24  *  10 -- random vaults\n
25  *  11 -- circular rooms\n
26  *  12 -- crypts\n
27  *  13 -- trapped monster pits\n
28  *  14 -- trapped room\n
29  *  15 -- glass room\n
30  *  16 -- underground arcade\n
31  *\n
32  * Some functions are used to determine if the given monster\n
33  * is appropriate for inclusion in a monster nest or monster pit or\n
34  * the given type.\n
35  *\n
36  * None of the pits/nests are allowed to include "unique" monsters.\n
37  */
38
39 #include "angband.h"
40 #include "generate.h"
41 #include "grid.h"
42 #include "rooms.h"
43
44 #include "rooms-city.h"
45 #include "rooms-fractal.h"
46 #include "rooms-normal.h"
47 #include "rooms-pitnest.h"
48 #include "rooms-special.h"
49 #include "rooms-trap.h"
50 #include "rooms-vault.h"
51
52 #include "trap.h"
53
54
55 /*!
56  * 各部屋タイプの生成比定義
57  *[from SAngband (originally from OAngband)]\n
58  *\n
59  * Table of values that control how many times each type of room will\n
60  * appear.  Each type of room has its own row, and each column\n
61  * corresponds to dungeon levels 0, 10, 20, and so on.  The final\n
62  * value is the minimum depth the room can appear at.  -LM-\n
63  *\n
64  * Level 101 and below use the values for level 100.\n
65  *\n
66  * Rooms with lots of monsters or loot may not be generated if the\n
67  * object or monster lists are already nearly full.  Rooms will not\n
68  * appear above their minimum depth.  Tiny levels will not have space\n
69  * for all the rooms you ask for.\n
70  */
71 static room_info_type room_info_normal[ROOM_T_MAX] =
72 {
73         /* Depth */
74         /*  0  10  20  30  40  50  60  70  80  90 100  min limit */
75
76         {{999,900,800,700,600,500,400,300,200,100,  0},  0}, /*NORMAL   */
77         {{  1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100},  1}, /*OVERLAP  */
78         {{  1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100},  3}, /*CROSS    */
79         {{  1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100},  3}, /*INNER_F  */
80         {{  0,  1,  1,  1,  2,  3,  5,  6,  8, 10, 13}, 10}, /*NEST     */
81         {{  0,  1,  1,  2,  3,  4,  6,  8, 10, 13, 16}, 10}, /*PIT      */
82         {{  0,  1,  1,  1,  2,  2,  3,  5,  6,  8, 10}, 10}, /*LESSER_V */
83         {{  0,  0,  1,  1,  1,  2,  2,  2,  3,  3,  4}, 20}, /*GREATER_V*/
84         {{  0,100,200,300,400,500,600,700,800,900,999}, 10}, /*FRACAVE  */
85         {{  0,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2}, 10}, /*RANDOM_V */
86         {{  0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40},  3}, /*OVAL     */
87         {{  1,  6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT    */
88         {{  0,  0,  1,  1,  1,  2,  3,  4,  5,  6,  8}, 20}, /*TRAP_PIT */
89         {{  0,  0,  1,  1,  1,  2,  3,  4,  5,  6,  8}, 20}, /*TRAP     */
90         {{  0,  0,  0,  0,  1,  1,  1,  2,  2,  2,  2}, 40}, /*GLASS    */
91         {{  1,  1,  1,  1,  1,  1,  1,  2,  2,  3,  3},  1}, /*ARCADE   */
92 };
93
94
95 /*! 部屋の生成処理順 / Build rooms in descending order of difficulty. */
96 static byte room_build_order[ROOM_T_MAX] = {
97         ROOM_T_GREATER_VAULT,
98         ROOM_T_ARCADE,
99         ROOM_T_RANDOM_VAULT,
100         ROOM_T_LESSER_VAULT,
101         ROOM_T_TRAP_PIT,
102         ROOM_T_PIT,
103         ROOM_T_NEST,
104         ROOM_T_TRAP,
105         ROOM_T_GLASS,
106         ROOM_T_INNER_FEAT,
107         ROOM_T_OVAL,
108         ROOM_T_CRYPT,
109         ROOM_T_OVERLAP,
110         ROOM_T_CROSS,
111         ROOM_T_FRACAVE,
112         ROOM_T_NORMAL,
113 };
114
115 /*!
116  * @brief 1マスだけの部屋を作成し、上下左右いずれか一つに隠しドアを配置する。
117  * @param y0 配置したい中心のY座標
118  * @param x0 配置したい中心のX座標
119  * @details
120  * This funtion makes a very small room centred at (x0, y0)
121  * This is used in crypts, and random elemental vaults.
122  *
123  * Note - this should be used only on allocated regions
124  * within another room.
125  */
126 void build_small_room(int x0, int y0)
127 {
128         int x, y;
129
130         for (y = y0 - 1; y <= y0 + 1; y++)
131         {
132                 place_inner_bold(y, x0 - 1);
133                 place_inner_bold(y, x0 + 1);
134         }
135
136         for (x = x0 - 1; x <= x0 + 1; x++)
137         {
138                 place_inner_bold(y0 - 1, x);
139                 place_inner_bold(y0 + 1, x);
140         }
141
142         /* Place a secret door on one side */
143         switch (randint0(4))
144         {
145                 case 0: place_secret_door(y0, x0 - 1, DOOR_DEFAULT); break;
146                 case 1: place_secret_door(y0, x0 + 1, DOOR_DEFAULT); break;
147                 case 2: place_secret_door(y0 - 1, x0, DOOR_DEFAULT); break;
148                 case 3: place_secret_door(y0 + 1, x0, DOOR_DEFAULT); break;
149         }
150
151         /* Clear mimic type */
152         cave[y0][x0].mimic = 0;
153
154         /* Add inner open space */
155         place_floor_bold(y0, x0);
156 }
157
158 /*!
159  * @brief
160  * 指定範囲に通路が通っていることを確認した上で床で埋める
161  * This function tunnels around a room if it will cut off part of a cave system.
162  * @param x1 範囲の左端
163  * @param y1 範囲の上端
164  * @param x2 範囲の右端
165  * @param y2 範囲の下端
166  * @return なし
167  */
168 static void check_room_boundary(int x1, int y1, int x2, int y2)
169 {
170         int count, x, y;
171         bool old_is_floor, new_is_floor;
172
173
174         /* Initialize */
175         count = 0;
176
177         old_is_floor = get_is_floor(x1 - 1, y1);
178
179         /*
180          * Count the number of floor-wall boundaries around the room
181          * Note: diagonal squares are ignored since the player can move diagonally
182          * to bypass these if needed.
183          */
184
185         /* Above the top boundary */
186         for (x = x1; x <= x2; x++)
187         {
188                 new_is_floor = get_is_floor(x, y1 - 1);
189
190                 /* Increment counter if they are different */
191                 if (new_is_floor != old_is_floor) count++;
192
193                 old_is_floor = new_is_floor;
194         }
195
196         /* Right boundary */
197         for (y = y1; y <= y2; y++)
198         {
199                 new_is_floor = get_is_floor(x2 + 1, y);
200
201                 /* increment counter if they are different */
202                 if (new_is_floor != old_is_floor) count++;
203
204                 old_is_floor = new_is_floor;
205         }
206
207         /* Bottom boundary */
208         for (x = x2; x >= x1; x--)
209         {
210                 new_is_floor = get_is_floor(x, y2 + 1);
211
212                 /* increment counter if they are different */
213                 if (new_is_floor != old_is_floor) count++;
214
215                 old_is_floor = new_is_floor;
216         }
217
218         /* Left boundary */
219         for (y = y2; y >= y1; y--)
220         {
221                 new_is_floor = get_is_floor(x1 - 1, y);
222
223                 /* increment counter if they are different */
224                 if (new_is_floor != old_is_floor) count++;
225
226                 old_is_floor = new_is_floor;
227         }
228
229         /* If all the same, or only one connection exit. */
230         if (count <= 2) return;
231
232
233         /* Tunnel around the room so to prevent problems with caves */
234         for (y = y1; y <= y2; y++)
235         {
236                 for (x = x1; x <= x2; x++)
237                 {
238                         set_floor(x, y);
239                 }
240         }
241 }
242
243
244 /*!
245  * @brief
246  * find_space()の予備処理として部屋の生成が可能かを判定する /
247  * Helper function for find_space(). Is this a good location?
248  * @param blocks_high 範囲の高さ
249  * @param blocks_wide 範囲の幅
250  * @param block_y 範囲の上端
251  * @param block_x 範囲の左端
252  * @return なし
253  */
254 static bool find_space_aux(int blocks_high, int blocks_wide, int block_y, int block_x)
255 {
256         int by1, bx1, by2, bx2, by, bx;
257
258         /* Itty-bitty rooms must shift about within their rectangle */
259         if (blocks_wide < 3)
260         {
261                 if ((blocks_wide == 2) && (block_x % 3) == 2)
262                         return FALSE;
263         }
264
265         /* Rooms with width divisible by 3 must be fitted to a rectangle. */
266         else if ((blocks_wide % 3) == 0)
267         {
268                 /* Must be aligned to the left edge of a 11x33 rectangle. */
269                 if ((block_x % 3) != 0)
270                         return FALSE;
271         }
272
273         /*
274          * Big rooms that do not have a width divisible by 3 must be
275          * aligned towards the edge of the dungeon closest to them.
276          */
277         else
278         {
279                 /* Shift towards left edge of dungeon. */
280                 if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
281                 {
282                         if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
283                                 return FALSE;
284                         if ((block_x % 3) == 1)
285                                 return FALSE;
286                 }
287
288                 /* Shift toward right edge of dungeon. */
289                 else
290                 {
291                         if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
292                                 return FALSE;
293                         if ((block_x % 3) == 1)
294                                 return FALSE;
295                 }
296         }
297
298         /* Extract blocks */
299         by1 = block_y + 0;
300         bx1 = block_x + 0;
301         by2 = block_y + blocks_high;
302         bx2 = block_x + blocks_wide;
303
304         /* Never run off the screen */
305         if ((by1 < 0) || (by2 > dun->row_rooms)) return FALSE;
306         if ((bx1 < 0) || (bx2 > dun->col_rooms)) return FALSE;
307         
308         /* Verify available space */
309         for (by = by1; by < by2; by++)
310         {
311                 for (bx = bx1; bx < bx2; bx++)
312                 {
313                         if (dun->room_map[by][bx])
314                         {
315                                 return FALSE;
316                         }
317                 }
318         }
319
320         /* This location is okay */
321         return TRUE;
322 }
323
324
325 /*!
326  * @brief 部屋生成が可能なスペースを確保する / Find a good spot for the next room.  -LM-
327  * @param y 部屋の生成が可能な中心Y座標を返す参照ポインタ
328  * @param x 部屋の生成が可能な中心X座標を返す参照ポインタ
329  * @param height 確保したい領域の高さ
330  * @param width 確保したい領域の幅
331  * @return 所定の範囲が確保できた場合TRUEを返す
332  * @details
333  * Find and allocate a free space in the dungeon large enough to hold\n
334  * the room calling this function.\n
335  *\n
336  * We allocate space in 11x11 blocks, but want to make sure that rooms\n
337  * align neatly on the standard screen.  Therefore, we make them use\n
338  * blocks in few 11x33 rectangles as possible.\n
339  *\n
340  * Be careful to include the edges of the room in height and width!\n
341  *\n
342  * Return TRUE and values for the center of the room if all went well.\n
343  * Otherwise, return FALSE.\n
344  */
345 bool find_space(POSITION *y, POSITION *x, POSITION height, POSITION width)
346 {
347         int candidates, pick;
348         int by, bx, by1, bx1, by2, bx2;
349         int block_y = 0, block_x = 0;
350
351
352         /* Find out how many blocks we need. */
353         int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
354         int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
355
356         /* There are no way to allocate such huge space */
357         if (dun->row_rooms < blocks_high) return FALSE;
358         if (dun->col_rooms < blocks_wide) return FALSE;
359
360         /* Initiallize */
361         candidates = 0;
362
363         /* Count the number of valid places */
364         for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
365         {
366                 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
367                 {
368                         if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
369                         {
370                                 /* Find a valid place */
371                                 candidates++;
372                         }
373                 }
374         }
375
376         /* No place! */
377         if (!candidates)
378         {
379                 return FALSE;
380         }
381
382         /* Normal dungeon */
383         if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE))
384         {
385                 /* Choose a random one */
386                 pick = randint1(candidates);
387         }
388
389         /* NO_CAVE dungeon (Castle) */
390         else
391         {
392                 /* Always choose the center one */
393                 pick = candidates/2 + 1;
394         }
395
396         /* Pick up the choosen location */
397         for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
398         {
399                 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
400                 {
401                         if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
402                         {
403                                 pick--;
404
405                                 /* This one is picked? */
406                                 if (!pick) break;
407                         }
408                 }
409
410                 if (!pick) break;
411         }
412
413         /* Extract blocks */
414         by1 = block_y + 0;
415         bx1 = block_x + 0;
416         by2 = block_y + blocks_high;
417         bx2 = block_x + blocks_wide;
418
419         /*
420          * It is *extremely* important that the following calculation
421          * be *exactly* correct to prevent memory errors
422          */
423
424         /* Acquire the location of the room */
425         (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
426         (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
427
428         /* Save the room location */
429         if (dun->cent_n < CENT_MAX)
430         {
431                 dun->cent[dun->cent_n].y = (byte_hack)*y;
432                 dun->cent[dun->cent_n].x = (byte_hack)*x;
433                 dun->cent_n++;
434         }
435
436         /* Reserve some blocks. */
437         for (by = by1; by < by2; by++)
438         {
439                 for (bx = bx1; bx < bx2; bx++)
440                 {
441                         dun->room_map[by][bx] = TRUE;
442                 }
443         }
444
445
446         /*
447          * Hack- See if room will cut off a cavern.
448          *
449          * If so, fix by tunneling outside the room in such a
450          * way as to connect the caves.
451          */
452         check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
453
454
455         /* Success. */
456         return TRUE;
457 }
458
459
460
461
462 /*
463  * Structure to hold all "fill" data
464  */
465
466 typedef struct fill_data_type fill_data_type;
467
468 struct fill_data_type
469 {
470         /* area size */
471         int xmin;
472         int ymin;
473         int xmax;
474         int ymax;
475
476         /* cutoffs */
477         int c1;
478         int c2;
479         int c3;
480
481         /* features to fill with */
482         int feat1;
483         int feat2;
484         int feat3;
485
486         int info1;
487         int info2;
488         int info3;
489
490         /* number of filled squares */
491         int amount;
492 };
493
494 static fill_data_type fill_data;
495
496
497 /* Store routine for the fractal cave generator */
498 /* this routine probably should be an inline function or a macro. */
499 static void store_height(int x, int y, int val)
500 {
501         /* if on boundary set val > cutoff so walls are not as square */
502         if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
503              (x == fill_data.xmax) || (y == fill_data.ymax)) &&
504             (val <= fill_data.c1)) val = fill_data.c1 + 1;
505
506         /* store the value in height-map format */
507         cave[y][x].feat = (s16b)val;
508
509         return;
510 }
511
512
513 /*
514 * Explanation of the plasma fractal algorithm:
515 *
516 * A grid of points is created with the properties of a 'height-map'
517 * This is done by making the corners of the grid have a random value.
518 * The grid is then subdivided into one with twice the resolution.
519 * The new points midway between two 'known' points can be calculated
520 * by taking the average value of the 'known' ones and randomly adding
521 * or subtracting an amount proportional to the distance between those
522 * points.  The final 'middle' points of the grid are then calculated
523 * by averaging all four of the originally 'known' corner points.  An
524 * random amount is added or subtracted from this to get a value of the
525 * height at that point.  The scaling factor here is adjusted to the
526 * slightly larger distance diagonally as compared to orthogonally.
527 *
528 * This is then repeated recursively to fill an entire 'height-map'
529 * A rectangular map is done the same way, except there are different
530 * scaling factors along the x and y directions.
531 *
532 * A hack to change the amount of correlation between points is done using
533 * the grd variable.  If the current step size is greater than grd then
534 * the point will be random, otherwise it will be calculated by the
535 * above algorithm.  This makes a maximum distance at which two points on
536 * the height map can affect each other.
537 *
538 * How fractal caves are made:
539 *
540 * When the map is complete, a cut-off value is used to create a cave.
541 * Heights below this value are "floor", and heights above are "wall".
542 * This also can be used to create lakes, by adding more height levels
543 * representing shallow and deep water/ lava etc.
544 *
545 * The grd variable affects the width of passages.
546 * The roug variable affects the roughness of those passages
547 *
548 * The tricky part is making sure the created cave is connected.  This
549 * is done by 'filling' from the inside and only keeping the 'filled'
550 * floor.  Walls bounding the 'filled' floor are also kept.  Everything
551 * else is converted to the normal _extra_.
552  */
553
554
555 /*
556  *  Note that this uses the cave.feat array in a very hackish way
557  *  the values are first set to zero, and then each array location
558  *  is used as a "heightmap"
559  *  The heightmap then needs to be converted back into the "feat" format.
560  *
561  *  grd=level at which fractal turns on.  smaller gives more mazelike caves
562  *  roug=roughness level.  16=normal.  higher values make things more convoluted
563  *    small values are good for smooth walls.
564  *  size=length of the side of the square cave system.
565  */
566 void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
567 {
568         int xhsize, yhsize, xsize, ysize, maxsize;
569
570         /*
571          * fixed point variables- these are stored as 256 x normal value
572          * this gives 8 binary places of fractional part + 8 places of normal part
573          */
574
575         u16b xstep, xhstep, ystep, yhstep;
576         u16b xstep2, xhstep2, ystep2, yhstep2;
577         u16b i, j, ii, jj, diagsize, xxsize, yysize;
578         
579         /* Cache for speed */
580         u16b xm, xp, ym, yp;
581
582         /* redefine size so can change the value if out of range */
583         xsize = xsiz;
584         ysize = ysiz;
585
586         /* Paranoia about size of the system of caves */
587         if (xsize > 254) xsize = 254;
588         if (xsize < 4) xsize = 4;
589         if (ysize > 254) ysize = 254;
590         if (ysize < 4) ysize = 4;
591
592         /* get offsets to middle of array */
593         xhsize = xsize / 2;
594         yhsize = ysize / 2;
595
596         /* fix rounding problem */
597         xsize = xhsize * 2;
598         ysize = yhsize * 2;
599
600         /* get limits of region */
601         fill_data.xmin = x0 - xhsize;
602         fill_data.ymin = y0 - yhsize;
603         fill_data.xmax = x0 + xhsize;
604         fill_data.ymax = y0 + yhsize;
605
606         /* Store cutoff in global for quick access */
607         fill_data.c1 = cutoff;
608
609         /*
610         * Scale factor for middle points:
611         * About sqrt(2) * 256 - correct for a square lattice
612         * approximately correct for everything else.
613          */
614         diagsize = 362;
615
616         /* maximum of xsize and ysize */
617         maxsize = (xsize > ysize) ? xsize : ysize;
618
619         /* Clear the section */
620         for (i = 0; i <= xsize; i++)
621         {
622                 for (j = 0; j <= ysize; j++)
623                 {
624                         /* -1 is a flag for "not done yet" */
625                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
626                         /* Clear icky flag because may be redoing the cave */
627                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
628                 }
629         }
630
631         /* Boundaries are walls */
632         cave[fill_data.ymin][fill_data.xmin].feat = (s16b)maxsize;
633         cave[fill_data.ymax][fill_data.xmin].feat = (s16b)maxsize;
634         cave[fill_data.ymin][fill_data.xmax].feat = (s16b)maxsize;
635         cave[fill_data.ymax][fill_data.xmax].feat = (s16b)maxsize;
636
637         /* Set the middle square to be an open area. */
638         cave[y0][x0].feat = 0;
639
640         /* Initialize the step sizes */
641         xstep = xhstep = xsize * 256;
642         ystep = yhstep = ysize * 256;
643         xxsize = xsize * 256;
644         yysize = ysize * 256;
645
646         /*
647          * Fill in the rectangle with fractal height data -
648          * like the 'plasma fractal' in fractint.
649          */
650         while ((xhstep > 256) || (yhstep > 256))
651         {
652                 /* Halve the step sizes */
653                 xstep = xhstep;
654                 xhstep /= 2;
655                 ystep = yhstep;
656                 yhstep /= 2;
657
658                 /* cache well used values */
659                 xstep2 = xstep / 256;
660                 ystep2 = ystep / 256;
661
662                 xhstep2 = xhstep / 256;
663                 yhstep2 = yhstep / 256;
664
665                 /* middle top to bottom. */
666                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
667                 {
668                         for (j = 0; j <= yysize; j += ystep)
669                         {
670                                 /* cache often used values */
671                                 ii = i / 256 + fill_data.xmin;
672                                 jj = j / 256 + fill_data.ymin;
673
674                                 /* Test square */
675                                 if (cave[jj][ii].feat == -1)
676                                 {
677                                         if (xhstep2 > grd)
678                                         {
679                                                 /* If greater than 'grid' level then is random */
680                                                 store_height(ii, jj, randint1(maxsize));
681                                         }
682                                         else
683                                         {
684                                                 /* Average of left and right points +random bit */
685                                                 store_height(ii, jj,
686                                                         (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
687                                                          + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
688                                                          + (randint1(xstep2) - xhstep2) * roug / 16);
689                                         }
690                                 }
691                         }
692                 }
693
694
695                 /* middle left to right. */
696                 for (j = yhstep; j <= yysize - yhstep; j += ystep)
697                 {
698                         for (i = 0; i <= xxsize; i += xstep)
699                         {
700                                 /* cache often used values */
701                                 ii = i / 256 + fill_data.xmin;
702                                 jj = j / 256 + fill_data.ymin;
703
704                                 /* Test square */
705                                 if (cave[jj][ii].feat == -1)
706                                 {
707                                         if (xhstep2 > grd)
708                                         {
709                                                 /* If greater than 'grid' level then is random */
710                                                 store_height(ii, jj, randint1(maxsize));
711                                         }
712                                         else
713                                         {
714                                                 /* Average of up and down points +random bit */
715                                                 store_height(ii, jj,
716                                                         (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
717                                                         + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
718                                                         + (randint1(ystep2) - yhstep2) * roug / 16);
719                                         }
720                                 }
721                         }
722                 }
723
724                 /* center. */
725                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
726                 {
727                         for (j = yhstep; j <= yysize - yhstep; j += ystep)
728                         {
729                                 /* cache often used values */
730                                 ii = i / 256 + fill_data.xmin;
731                                 jj = j / 256 + fill_data.ymin;
732
733                                 /* Test square */
734                                 if (cave[jj][ii].feat == -1)
735                                 {
736                                         if (xhstep2 > grd)
737                                         {
738                                                 /* If greater than 'grid' level then is random */
739                                                 store_height(ii, jj, randint1(maxsize));
740                                         }
741                                         else
742                                         {
743                                                 /* Cache reused values. */
744                                                 xm = fill_data.xmin + (i - xhstep) / 256;
745                                                 xp = fill_data.xmin + (i + xhstep) / 256;
746                                                 ym = fill_data.ymin + (j - yhstep) / 256;
747                                                 yp = fill_data.ymin + (j + yhstep) / 256;
748
749                                                 /* 
750                                                  * Average over all four corners + scale by diagsize to
751                                                  * reduce the effect of the square grid on the shape of the fractal
752                                                  */
753                                                 store_height(ii, jj,
754                                                         (cave[ym][xm].feat + cave[yp][xm].feat
755                                                         + cave[ym][xp].feat + cave[yp][xp].feat) / 4
756                                                         + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
757                                         }
758                                 }
759                         }
760                 }
761         }
762 }
763
764
765 static bool hack_isnt_wall(int y, int x, int c1, int c2, int c3, int feat1, int feat2, int feat3, int info1, int info2, int info3)
766 {
767         /*
768          * function used to convert from height-map back to the
769          *  normal angband cave format
770          */
771         if (cave[y][x].info & CAVE_ICKY)
772         {
773                 /* already done */
774                 return FALSE;
775         }
776         else
777         {
778                 /* Show that have looked at this square */
779                 cave[y][x].info|= (CAVE_ICKY);
780
781                 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
782                 if (cave[y][x].feat <= c1)
783                 {
784                         /* 25% of the time use the other tile : it looks better this way */
785                         if (randint1(100) < 75)
786                         {
787                                 cave[y][x].feat = (s16b)feat1;
788                                 cave[y][x].info &= ~(CAVE_MASK);
789                                 cave[y][x].info |= info1;
790                                 return TRUE;
791                         }
792                         else
793                         {
794                                 cave[y][x].feat = (s16b)feat2;
795                                 cave[y][x].info &= ~(CAVE_MASK);
796                                 cave[y][x].info |= info2;
797                                 return TRUE;
798                         }
799                 }
800                 else if (cave[y][x].feat <= c2)
801                 {
802                         /* 25% of the time use the other tile : it looks better this way */
803                         if (randint1(100) < 75)
804                         {
805                                 cave[y][x].feat = (s16b)feat2;
806                                 cave[y][x].info &= ~(CAVE_MASK);
807                                 cave[y][x].info |= info2;
808                                 return TRUE;
809                         }
810                         else
811                         {
812                                 cave[y][x].feat = (s16b)feat1;
813                                 cave[y][x].info &= ~(CAVE_MASK);
814                                 cave[y][x].info |= info1;
815                                 return TRUE;
816                         }
817                 }
818                 else if (cave[y][x].feat <= c3)
819                 {
820                         cave[y][x].feat = (s16b)feat3;
821                         cave[y][x].info &= ~(CAVE_MASK);
822                         cave[y][x].info |= info3;
823                         return TRUE;
824                 }
825                 /* if greater than cutoff then is a wall */
826                 else
827                 {
828                         place_outer_bold(y, x);
829                         return FALSE;
830                 }
831         }
832 }
833
834
835
836
837 /*
838  * Quick and nasty fill routine used to find the connected region
839  * of floor in the middle of the cave
840  */
841 static void cave_fill(POSITION y, POSITION x)
842 {
843         int i, j, d;
844         int ty, tx;
845
846         int flow_tail = 1;
847         int flow_head = 0;
848
849
850         /*** Start Grid ***/
851
852         /* Enqueue that entry */
853         temp_y[0] = y;
854         temp_x[0] = x;
855
856
857         /* Now process the queue */
858         while (flow_head != flow_tail)
859         {
860                 /* Extract the next entry */
861                 ty = temp_y[flow_head];
862                 tx = temp_x[flow_head];
863
864                 /* Forget that entry */
865                 if (++flow_head == TEMP_MAX) flow_head = 0;
866
867                 /* Add the "children" */
868                 for (d = 0; d < 8; d++)
869                 {
870                         int old_head = flow_tail;
871
872                         /* Child location */
873                         j = ty + ddy_ddd[d];
874                         i = tx + ddx_ddd[d];
875
876                         /* Paranoia Don't leave the cave */
877                         if (!in_bounds(j, i))
878                         {
879                                 /* affect boundary */
880                                 cave[j][i].info |= CAVE_ICKY;
881 /*                              return; */
882                         }
883
884                         /* If within bounds */
885                         else if ((i > fill_data.xmin) && (i < fill_data.xmax)
886                                 && (j > fill_data.ymin) && (j < fill_data.ymax))
887                         {
888                                 /* If not a wall or floor done before */
889                                 if (hack_isnt_wall(j, i,
890                                         fill_data.c1, fill_data.c2, fill_data.c3,
891                                         fill_data.feat1, fill_data.feat2, fill_data.feat3,
892                                         fill_data.info1, fill_data.info2, fill_data.info3))
893                                 {
894                                         /* Enqueue that entry */
895                                         temp_y[flow_tail] = (byte_hack)j;
896                                         temp_x[flow_tail] = (byte_hack)i;
897
898                                         /* Advance the queue */
899                                         if (++flow_tail == TEMP_MAX) flow_tail = 0;
900
901                                         /* Hack -- Overflow by forgetting new entry */
902                                         if (flow_tail == flow_head)
903                                         {
904                                                 flow_tail = old_head;
905                                         }
906                                         else
907                                         {
908                                                 /* keep tally of size of cave system */
909                                                 (fill_data.amount)++;
910                                         }
911                                 }
912                         }
913                         else
914                         {
915                                 /* affect boundary */
916                                 cave[j][i].info |= CAVE_ICKY;
917                         }
918                 }
919         }
920 }
921
922
923 bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
924 {
925         int x, y, i, xhsize, yhsize;
926
927         /* offsets to middle from corner */
928         xhsize = xsize / 2;
929         yhsize = ysize / 2;
930
931
932         /*
933          * select region connected to center of cave system
934          * this gets rid of alot of isolated one-sqaures that
935          * can make teleport traps instadeaths...
936          */
937
938         /* cutoffs */
939         fill_data.c1 = cutoff;
940         fill_data.c2 = 0;
941         fill_data.c3 = 0;
942
943         /* features to fill with */
944         fill_data.feat1 = floor_type[randint0(100)];
945         fill_data.feat2 = floor_type[randint0(100)];
946         fill_data.feat3 = floor_type[randint0(100)];
947
948         fill_data.info1 = CAVE_FLOOR;
949         fill_data.info2 = CAVE_FLOOR;
950         fill_data.info3 = CAVE_FLOOR;
951
952         /* number of filled squares */
953         fill_data.amount = 0;
954
955         cave_fill((byte)y0, (byte)x0);
956
957         /* if tally too small, try again */
958         if (fill_data.amount < 10)
959         {
960                 /* too small - clear area and try again later */
961                 for (x = 0; x <= xsize; ++x)
962                 {
963                         for (y = 0; y <= ysize; ++y)
964                         {
965                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
966                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
967                         }
968                 }
969                 return FALSE;
970         }
971
972         /*
973          * Do boundarys-check to see if they are next to a filled region
974          * If not then they are set to normal granite
975          * If so then they are marked as room walls.
976          */
977         for (i = 0; i <= xsize; ++i)
978         {
979                 /* top boundary */
980                 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
981                 {
982                         /* Next to a 'filled' region? - set to be room walls */
983                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
984                         if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
985                         cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
986                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
987                 }
988                 else
989                 {
990                         /* set to be normal granite */
991                         place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
992                 }
993
994                 /* bottom boundary */
995                 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
996                 {
997                         /* Next to a 'filled' region? - set to be room walls */
998                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
999                         if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
1000                         cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
1001                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1002                 }
1003                 else
1004                 {
1005                         /* set to be normal granite */
1006                         place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1007                 }
1008
1009                 /* clear the icky flag-don't need it any more */
1010                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1011                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1012         }
1013
1014         /* Do the left and right boundaries minus the corners (done above) */
1015         for (i = 1; i < ysize; ++i)
1016         {
1017                 /* left boundary */
1018                 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
1019                 {
1020                         /* room boundary */
1021                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1022                         if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
1023                         cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
1024                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1025                 }
1026                 else
1027                 {
1028                         /* outside room */
1029                         place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1030                 }
1031                 /* right boundary */
1032                 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
1033                 {
1034                         /* room boundary */
1035                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1036                         if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
1037                         cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
1038                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1039                 }
1040                 else
1041                 {
1042                         /* outside room */
1043                         place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1044                 }
1045
1046                 /* clear icky flag -done with it */
1047                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
1048                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
1049         }
1050
1051
1052         /* Do the rest: convert back to the normal format */
1053         for (x = 1; x < xsize; ++x)
1054         {
1055                 for (y = 1; y < ysize; ++y)
1056                 {
1057                         if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
1058                             (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
1059                         {
1060                                 /* Clear the icky flag in the filled region */
1061                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
1062
1063                                 /* Set appropriate flags */
1064                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
1065                                 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
1066                         }
1067                         else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
1068                                  (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
1069                         {
1070                                 /* Walls */
1071                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
1072                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
1073                                 if (room)
1074                                 {
1075                                         cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
1076                                 }
1077                                 else
1078                                 {
1079
1080                                         place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1081                                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
1082                                 }
1083                         }
1084                         else
1085                         {
1086                                 /* Clear the unconnected regions */
1087                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1088                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
1089                         }
1090                 }
1091         }
1092
1093         /*
1094          * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
1095          * Extra doors appear inside the system.  (Its not very noticeable though.)
1096          * This can be removed by "filling" from the outside in.  This allows a separation
1097          * from _outer_ with _inner_.  (Internal walls are  _outer_ instead.)
1098          * The extra effort for what seems to be only a minor thing (even non-existant if you
1099          * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
1100          * worth it.
1101          */
1102
1103         return TRUE;
1104 }
1105
1106
1107 #ifdef ALLOW_CAVERNS_AND_LAKES
1108 /*
1109  * Builds a cave system in the center of the dungeon.
1110  */
1111 void build_cavern(void)
1112 {
1113         int grd, roug, cutoff, xsize, ysize, x0, y0;
1114         bool done, light;
1115
1116         light = done = FALSE;
1117         if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
1118
1119         /* Make a cave the size of the dungeon */
1120         xsize = cur_wid - 1;
1121         ysize = cur_hgt - 1;
1122         x0 = xsize / 2;
1123         y0 = ysize / 2;
1124
1125         /* Paranoia: make size even */
1126         xsize = x0 * 2;
1127         ysize = y0 * 2;
1128
1129         while (!done)
1130         {
1131                 /* testing values for these parameters: feel free to adjust */
1132                 grd = randint1(4) + 4;
1133
1134                 /* want average of about 16 */
1135                 roug = randint1(8) * randint1(4);
1136
1137                 /* about size/2 */
1138                 cutoff = xsize / 2;
1139
1140                  /* make it */
1141                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
1142
1143                 /* Convert to normal format+ clean up */
1144                 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
1145         }
1146 }
1147
1148 bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
1149 {
1150         int x, y, i, xhsize, yhsize;
1151         int feat1, feat2, feat3;
1152
1153         /* offsets to middle from corner */
1154         xhsize = xsize / 2;
1155         yhsize = ysize / 2;
1156
1157         /* Get features based on type */
1158         switch (type)
1159         {
1160         case LAKE_T_LAVA: /* Lava */
1161                 feat1 = feat_deep_lava;
1162                 feat2 = feat_shallow_lava;
1163                 feat3 = floor_type[randint0(100)];
1164                 break;
1165         case LAKE_T_WATER: /* Water */
1166                 feat1 = feat_deep_water;
1167                 feat2 = feat_shallow_water;
1168                 feat3 = floor_type[randint0(100)];
1169                 break;
1170         case LAKE_T_CAVE: /* Collapsed cave */
1171                 feat1 = floor_type[randint0(100)];
1172                 feat2 = floor_type[randint0(100)];
1173                 feat3 = feat_rubble;
1174                 break;
1175         case LAKE_T_EARTH_VAULT: /* Earth vault */
1176                 feat1 = feat_rubble;
1177                 feat2 = floor_type[randint0(100)];
1178                 feat3 = feat_rubble;
1179                 break;
1180         case LAKE_T_AIR_VAULT: /* Air vault */
1181                 feat1 = feat_grass;
1182                 feat2 = feat_tree;
1183                 feat3 = feat_grass;
1184                 break;
1185         case LAKE_T_WATER_VAULT: /* Water vault */
1186                 feat1 = feat_shallow_water;
1187                 feat2 = feat_deep_water;
1188                 feat3 = feat_shallow_water;
1189                 break;
1190         case LAKE_T_FIRE_VAULT: /* Fire Vault */
1191                 feat1 = feat_shallow_lava;
1192                 feat2 = feat_deep_lava;
1193                 feat3 = feat_shallow_lava;
1194                 break;
1195
1196         /* Paranoia */
1197         default: return FALSE;
1198         }
1199
1200         /*
1201          * select region connected to center of cave system
1202          * this gets rid of alot of isolated one-sqaures that
1203          * can make teleport traps instadeaths...
1204          */
1205
1206         /* cutoffs */
1207         fill_data.c1 = c1;
1208         fill_data.c2 = c2;
1209         fill_data.c3 = c3;
1210
1211         /* features to fill with */
1212         fill_data.feat1 = feat1;
1213         fill_data.feat2 = feat2;
1214         fill_data.feat3 = feat3;
1215
1216         fill_data.info1 = 0;
1217         fill_data.info2 = 0;
1218         fill_data.info3 = 0;
1219
1220         /* number of filled squares */
1221         fill_data.amount = 0;
1222
1223         /* select region connected to center of cave system
1224         * this gets rid of alot of isolated one-sqaures that
1225         * can make teleport traps instadeaths... */
1226         cave_fill((byte)y0, (byte)x0);
1227
1228         /* if tally too small, try again */
1229         if (fill_data.amount < 10)
1230         {
1231                 /* too small -clear area and try again later */
1232                 for (x = 0; x <= xsize; ++x)
1233                 {
1234                         for (y = 0; y <= ysize; ++y)
1235                         {
1236                                 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
1237                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
1238                         }
1239                 }
1240                 return FALSE;
1241         }
1242
1243         /* Do boundarys- set to normal granite */
1244         for (i = 0; i <= xsize; ++i)
1245         {
1246                 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
1247                 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1248
1249                 /* clear the icky flag-don't need it any more */
1250                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1251                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1252         }
1253
1254         /* Do the left and right boundaries minus the corners (done above) */
1255
1256         for (i = 1; i < ysize; ++i)
1257         {
1258                 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1259                 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1260
1261                 /* clear icky flag -done with it */
1262                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
1263                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
1264         }
1265
1266
1267         /* Do the rest: convert back to the normal format */
1268         for (x = 1; x < xsize; ++x)
1269         {
1270                 for (y = 1; y < ysize; ++y)
1271                 {
1272                         /* Fill unconnected regions with granite */
1273                         if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
1274                                 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
1275                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1276
1277                         /* turn off icky flag (no longer needed.) */
1278                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
1279
1280                         /* Light lava */
1281                         if (cave_have_flag_bold(y0 + y - yhsize, x0 + x - xhsize, FF_LAVA))
1282                         {
1283                                 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
1284                         }
1285                 }
1286         }
1287
1288         return TRUE;
1289 }
1290
1291
1292 /*
1293  * makes a lake/collapsed cave system in the center of the dungeon
1294  */
1295 void build_lake(int type)
1296 {
1297         int grd, roug, xsize, ysize, x0, y0;
1298         bool done = FALSE;
1299         int c1, c2, c3;
1300
1301         /* paranoia - exit if lake type out of range. */
1302         if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
1303         {
1304                 msg_format("Invalid lake type (%d)", type);
1305                 return;
1306         }
1307
1308         /* Make the size of the dungeon */
1309         xsize = cur_wid - 1;
1310         ysize = cur_hgt - 1;
1311         x0 = xsize / 2;
1312         y0 = ysize / 2;
1313
1314         /* Paranoia: make size even */
1315         xsize = x0 * 2;
1316         ysize = y0 * 2;
1317
1318         while (!done)
1319         {
1320                 /* testing values for these parameters: feel free to adjust */
1321                 grd = randint1(3) + 4;
1322
1323                 /* want average of about 16 */
1324                 roug = randint1(8) * randint1(4);
1325
1326                 /* Make up size of various componants */
1327                 /* Floor */
1328                 c3 = 3 * xsize / 4;
1329
1330                 /* Deep water/lava */
1331                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
1332
1333                 /* Shallow boundary */
1334                 c2 = (c1 + c3) / 2;
1335
1336                 /* make it */
1337                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
1338
1339                 /* Convert to normal format+ clean up */
1340                 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
1341         }
1342 }
1343 #endif /* ALLOW_CAVERNS_AND_LAKES */
1344
1345
1346
1347 /*
1348  * Routine that fills the empty areas of a room with treasure and monsters.
1349  */
1350 void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
1351 {
1352         int x, y, cx, cy, size;
1353         s32b value;
1354
1355         /* center of room:*/
1356         cx = (x1 + x2) / 2;
1357         cy = (y1 + y2) / 2;
1358
1359         /* Rough measure of size of vault= sum of lengths of sides */
1360         size = abs(x2 - x1) + abs(y2 - y1);
1361
1362         for (x = x1; x <= x2; x++)
1363         {
1364                 for (y = y1; y <= y2; y++)
1365                 {
1366                         /* Thing added based on distance to center of vault
1367                          * Difficulty is 1-easy to 10-hard */
1368                         value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
1369
1370                         /* hack- empty square part of the time */
1371                         if ((randint1(100) - difficulty * 3) > 50) value = 20;
1372
1373                          /* if floor, shallow water and lava */
1374                         if (is_floor_bold(y, x) ||
1375                             (cave_have_flag_bold(y, x, FF_PLACE) && cave_have_flag_bold(y, x, FF_DROP)))
1376                         {
1377                                 /* The smaller 'value' is, the better the stuff */
1378                                 if (value < 0)
1379                                 {
1380                                         /* Meanest monster + treasure */
1381                                         monster_level = base_level + 40;
1382                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1383                                         monster_level = base_level;
1384                                         object_level = base_level + 20;
1385                                         place_object(y, x, AM_GOOD);
1386                                         object_level = base_level;
1387                                 }
1388                                 else if (value < 5)
1389                                 {
1390                                         /* Mean monster +treasure */
1391                                         monster_level = base_level + 20;
1392                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1393                                         monster_level = base_level;
1394                                         object_level = base_level + 10;
1395                                         place_object(y, x, AM_GOOD);
1396                                         object_level = base_level;
1397                                 }
1398                                 else if (value < 10)
1399                                 {
1400                                         /* Monster */
1401                                         monster_level = base_level + 9;
1402                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1403                                         monster_level = base_level;
1404                                 }
1405                                 else if (value < 17)
1406                                 {
1407                                         /* Intentional Blank space */
1408
1409                                         /*
1410                                          * (Want some of the vault to be empty
1411                                          * so have room for group monsters.
1412                                          * This is used in the hack above to lower
1413                                          * the density of stuff in the vault.)
1414                                          */
1415                                 }
1416                                 else if (value < 23)
1417                                 {
1418                                         /* Object or trap */
1419                                         if (randint0(100) < 25)
1420                                         {
1421                                                 place_object(y, x, 0L);
1422                                         }
1423                                         else
1424                                         {
1425                                                 place_trap(y, x);
1426                                         }
1427                                 }
1428                                 else if (value < 30)
1429                                 {
1430                                         /* Monster and trap */
1431                                         monster_level = base_level + 5;
1432                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1433                                         monster_level = base_level;
1434                                         place_trap(y, x);
1435                                 }
1436                                 else if (value < 40)
1437                                 {
1438                                         /* Monster or object */
1439                                         if (randint0(100) < 50)
1440                                         {
1441                                                 monster_level = base_level + 3;
1442                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1443                                                 monster_level = base_level;
1444                                         }
1445                                         if (randint0(100) < 50)
1446                                         {
1447                                                 object_level = base_level + 7;
1448                                                 place_object(y, x, 0L);
1449                                                 object_level = base_level;
1450                                         }
1451                                 }
1452                                 else if (value < 50)
1453                                 {
1454                                         /* Trap */
1455                                         place_trap(y, x);
1456                                 }
1457                                 else
1458                                 {
1459                                         /* Various Stuff */
1460
1461                                         /* 20% monster, 40% trap, 20% object, 20% blank space */
1462                                         if (randint0(100) < 20)
1463                                         {
1464                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1465                                         }
1466                                         else if (randint0(100) < 50)
1467                                         {
1468                                                 place_trap(y, x);
1469                                         }
1470                                         else if (randint0(100) < 50)
1471                                         {
1472                                                 place_object(y, x, 0L);
1473                                         }
1474                                 }
1475
1476                         }
1477                 }
1478         }
1479 }
1480
1481
1482
1483 /*
1484  * Overlay a rectangular room given its bounds
1485  * This routine is used by build_room_vault
1486  * The area inside the walls is not touched:
1487  * only granite is removed- normal walls stay
1488  */
1489 void build_room(int x1, int x2, int y1, int y2)
1490 {
1491         int x, y, i, xsize, ysize, temp;
1492
1493         /* Check if rectangle has no width */
1494         if ((x1 == x2) || (y1 == y2)) return;
1495
1496         /* initialize */
1497         if (x1 > x2)
1498         {
1499                 /* Swap boundaries if in wrong order */
1500                 temp = x1;
1501                 x1 = x2;
1502                 x2 = temp;
1503         }
1504
1505         if (y1 > y2)
1506         {
1507                 /* Swap boundaries if in wrong order */
1508                 temp = y1;
1509                 y1 = y2;
1510                 y2 = temp;
1511         }
1512
1513         /* get total widths */
1514         xsize = x2 - x1;
1515         ysize = y2 - y1;
1516
1517
1518         /* Top and bottom boundaries */
1519         for (i = 0; i <= xsize; i++)
1520         {
1521                 place_outer_noperm_bold(y1, x1 + i);
1522                 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
1523                 place_outer_noperm_bold(y2, x1 + i);
1524                 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
1525         }
1526
1527         /* Left and right boundaries */
1528         for (i = 1; i < ysize; i++)
1529         {
1530                 place_outer_noperm_bold(y1 + i, x1);
1531                 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
1532                 place_outer_noperm_bold(y1 + i, x2);
1533                 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
1534         }
1535
1536         /* Middle */
1537         for (x = 1; x < xsize; x++)
1538         {
1539                 for (y = 1; y < ysize; y++)
1540                 {
1541                         if (is_extra_bold(y1+y, x1+x))
1542                         {
1543                                 /* clear the untouched region */
1544                                 place_floor_bold(y1 + y, x1 + x);
1545                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
1546                         }
1547                         else
1548                         {
1549                                 /* make it a room- but don't touch */
1550                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
1551                         }
1552                 }
1553         }
1554 }
1555
1556
1557
1558 /*
1559  * maze vault -- rectangular labyrinthine rooms
1560  *
1561  * maze vault uses two routines:
1562  *    r_visit - a recursive routine that builds the labyrinth
1563  *    build_maze_vault - a driver routine that calls r_visit and adds
1564  *                   monsters, traps and treasure
1565  *
1566  * The labyrinth is built by creating a spanning tree of a graph.
1567  * The graph vertices are at
1568  *    (x, y) = (2j + x1, 2k + y1)   j = 0,...,m-1    k = 0,...,n-1
1569  * and the edges are the vertical and horizontal nearest neighbors.
1570  *
1571  * The spanning tree is created by performing a suitably randomized
1572  * depth-first traversal of the graph. The only adjustable parameter
1573  * is the randint0(3) below; it governs the relative density of
1574  * twists and turns in the labyrinth: smaller number, more twists.
1575  */
1576 void r_visit(int y1, int x1, int y2, int x2, int node, int dir, int *visited)
1577 {
1578         int i, j, m, n, temp, x, y, adj[4];
1579
1580         /* dimensions of vertex array */
1581         m = (x2 - x1) / 2 + 1;
1582         n = (y2 - y1) / 2 + 1;
1583
1584         /* mark node visited and set it to a floor */
1585         visited[node] = 1;
1586         x = 2 * (node % m) + x1;
1587         y = 2 * (node / m) + y1;
1588         place_floor_bold(y, x);
1589
1590         /* setup order of adjacent node visits */
1591         if (one_in_(3))
1592         {
1593                 /* pick a random ordering */
1594                 for (i = 0; i < 4; i++)
1595                         adj[i] = i;
1596                 for (i = 0; i < 4; i++)
1597                 {
1598                         j = randint0(4);
1599                         temp = adj[i];
1600                         adj[i] = adj[j];
1601                         adj[j] = temp;
1602                 }
1603                 dir = adj[0];
1604         }
1605         else
1606         {
1607                 /* pick a random ordering with dir first */
1608                 adj[0] = dir;
1609                 for (i = 1; i < 4; i++)
1610                         adj[i] = i;
1611                 for (i = 1; i < 4; i++)
1612                 {
1613                         j = 1 + randint0(3);
1614                         temp = adj[i];
1615                         adj[i] = adj[j];
1616                         adj[j] = temp;
1617                 }
1618         }
1619
1620         for (i = 0; i < 4; i++)
1621         {
1622                 switch (adj[i])
1623                 {
1624                         case 0:
1625                                 /* (0,+) - check for bottom boundary */
1626                                 if ((node / m < n - 1) && (visited[node + m] == 0))
1627                                 {
1628                                         place_floor_bold(y + 1, x);
1629                                         r_visit(y1, x1, y2, x2, node + m, dir, visited);
1630                                 }
1631                                 break;
1632                         case 1:
1633                                 /* (0,-) - check for top boundary */
1634                                 if ((node / m > 0) && (visited[node - m] == 0))
1635                                 {
1636                                         place_floor_bold(y - 1, x);
1637                                         r_visit(y1, x1, y2, x2, node - m, dir, visited);
1638                                 }
1639                                 break;
1640                         case 2:
1641                                 /* (+,0) - check for right boundary */
1642                                 if ((node % m < m - 1) && (visited[node + 1] == 0))
1643                                 {
1644                                         place_floor_bold(y, x + 1);
1645                                         r_visit(y1, x1, y2, x2, node + 1, dir, visited);
1646                                 }
1647                                 break;
1648                         case 3:
1649                                 /* (-,0) - check for left boundary */
1650                                 if ((node % m > 0) && (visited[node - 1] == 0))
1651                                 {
1652                                         place_floor_bold(y, x - 1);
1653                                         r_visit(y1, x1, y2, x2, node - 1, dir, visited);
1654                                 }
1655                 } /* end switch */
1656         }
1657 }
1658
1659
1660 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
1661 {
1662         int y, x, dy, dx;
1663         int y1, x1, y2, x2;
1664         int m, n, num_vertices, *visited;
1665         bool light;
1666         cave_type *c_ptr;
1667
1668         msg_print_wizard(CHEAT_DUNGEON, _("迷路ランダムVaultを生成しました。", "Maze Vault."));
1669
1670         /* Choose lite or dark */
1671         light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
1672
1673         /* Pick a random room size - randomized by calling routine */
1674         dy = ysize / 2 - 1;
1675         dx = xsize / 2 - 1;
1676
1677         y1 = y0 - dy;
1678         x1 = x0 - dx;
1679         y2 = y0 + dy;
1680         x2 = x0 + dx;
1681
1682         /* generate the room */
1683         for (y = y1 - 1; y <= y2 + 1; y++)
1684         {
1685                 for (x = x1 - 1; x <= x2 + 1; x++)
1686                 {
1687                         c_ptr = &cave[y][x];
1688                         c_ptr->info |= CAVE_ROOM;
1689                         if (is_vault) c_ptr->info |= CAVE_ICKY;
1690                         if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
1691                         {
1692                                 place_outer_grid(c_ptr);
1693                         }
1694                         else if (!is_vault)
1695                         {
1696                                 place_extra_grid(c_ptr);
1697                         }
1698                         else
1699                         {
1700                                 place_inner_grid(c_ptr);
1701                         }
1702                         if (light) c_ptr->info |= (CAVE_GLOW);
1703                 }
1704         }
1705
1706         /* dimensions of vertex array */
1707         m = dx + 1;
1708         n = dy + 1;
1709         num_vertices = m * n;
1710
1711         /* initialize array of visited vertices */
1712         C_MAKE(visited, num_vertices, int);
1713
1714         /* traverse the graph to create a spaning tree, pick a random root */
1715         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
1716
1717         /* Fill with monsters and treasure, low difficulty */
1718         if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
1719
1720         C_KILL(visited, num_vertices, int);
1721 }
1722
1723
1724 /* Build a town/ castle by using a recursive algorithm.
1725  * Basically divide each region in a probalistic way to create
1726  * smaller regions.  When the regions get too small stop.
1727  *
1728  * The power variable is a measure of how well defended a region is.
1729  * This alters the possible choices.
1730  */
1731 void build_recursive_room(int x1, int y1, int x2, int y2, int power)
1732 {
1733         int xsize, ysize;
1734         int x, y;
1735         int choice;
1736
1737         /* Temp variables */
1738         int t1, t2, t3, t4;
1739
1740         xsize = x2 - x1;
1741         ysize = y2 - y1;
1742
1743         if ((power < 3) && (xsize > 12) && (ysize > 12))
1744         {
1745                 /* Need outside wall +keep */
1746                 choice = 1;
1747         }
1748         else
1749         {
1750                 if (power < 10)
1751                 {
1752                         /* Make rooms + subdivide */
1753                         if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
1754                         {
1755                                 choice = 4;
1756                         }
1757                         else
1758                         {
1759                                 choice = randint1(2) + 1;
1760                         }
1761                 }
1762                 else
1763                 {
1764                         /* Mostly subdivide */
1765                         choice = randint1(3) + 1;
1766                 }
1767         }
1768
1769         /* Based on the choice made above, do something */
1770
1771         switch (choice)
1772         {
1773                 case 1:
1774                 {
1775                         /* Outer walls */
1776
1777                         /* top and bottom */
1778                         for (x = x1; x <= x2; x++)
1779                         {
1780                                 place_outer_bold(y1, x);
1781                                 place_outer_bold(y2, x);
1782                         }
1783
1784                         /* left and right */
1785                         for (y = y1 + 1; y < y2; y++)
1786                         {
1787                                 place_outer_bold(y, x1);
1788                                 place_outer_bold(y, x2);
1789                         }
1790
1791                         /* Make a couple of entrances */
1792                         if (one_in_(2))
1793                         {
1794                                 /* left and right */
1795                                 y = randint1(ysize) + y1;
1796                                 place_floor_bold(y, x1);
1797                                 place_floor_bold(y, x2);
1798                         }
1799                         else
1800                         {
1801                                 /* top and bottom */
1802                                 x = randint1(xsize) + x1;
1803                                 place_floor_bold(y1, x);
1804                                 place_floor_bold(y2, x);
1805                         }
1806
1807                         /* Select size of keep */
1808                         t1 = randint1(ysize / 3) + y1;
1809                         t2 = y2 - randint1(ysize / 3);
1810                         t3 = randint1(xsize / 3) + x1;
1811                         t4 = x2 - randint1(xsize / 3);
1812
1813                         /* Do outside areas */
1814
1815                         /* Above and below keep */
1816                         build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
1817                         build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
1818
1819                         /* Left and right of keep */
1820                         build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
1821                         build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
1822
1823                         /* Make the keep itself: */
1824                         x1 = t3;
1825                         x2 = t4;
1826                         y1 = t1;
1827                         y2 = t2;
1828                         xsize = x2 - x1;
1829                         ysize = y2 - y1;
1830                         power += 2;
1831
1832                         /* Fall through */
1833                 }
1834                 case 4:
1835                 {
1836                         /* Try to build a room */
1837                         if ((xsize < 3) || (ysize < 3))
1838                         {
1839                                 for (y = y1; y < y2; y++)
1840                                 {
1841                                         for (x = x1; x < x2; x++)
1842                                         {
1843                                                 place_inner_bold(y, x);
1844                                         }
1845                                 }
1846
1847                                 /* Too small */
1848                                 return;
1849                         }
1850
1851                         /* Make outside walls */
1852                         /* top and bottom */
1853                         for (x = x1 + 1; x <= x2 - 1; x++)
1854                         {
1855                                 place_inner_bold(y1 + 1, x);
1856                                 place_inner_bold(y2 - 1, x);
1857                         }
1858
1859                         /* left and right */
1860                         for (y = y1 + 1; y <= y2 - 1; y++)
1861                         {
1862                                 place_inner_bold(y, x1 + 1);
1863                                 place_inner_bold(y, x2 - 1);
1864                         }
1865
1866                         /* Make a door */
1867                         y = randint1(ysize - 3) + y1 + 1;
1868
1869                         if (one_in_(2))
1870                         {
1871                                 /* left */
1872                                 place_floor_bold(y, x1 + 1);
1873                         }
1874                         else
1875                         {
1876                                 /* right */
1877                                 place_floor_bold(y, x2 - 1);
1878                         }
1879
1880                         /* Build the room */
1881                         build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
1882                         break;
1883                 }
1884                 case 2:
1885                 {
1886                         /* Try and divide vertically */
1887                         if (xsize < 3)
1888                         {
1889                                 /* Too small */
1890                                 for (y = y1; y < y2; y++)
1891                                 {
1892                                         for (x = x1; x < x2; x++)
1893                                         {
1894                                                 place_inner_bold(y, x);
1895                                         }
1896                                 }
1897                                 return;
1898                         }
1899
1900                         t1 = randint1(xsize - 2) + x1 + 1;
1901                         build_recursive_room(x1, y1, t1, y2, power - 2);
1902                         build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
1903                         break;
1904                 }
1905                 case 3:
1906                 {
1907                         /* Try and divide horizontally */
1908                         if (ysize < 3)
1909                         {
1910                                 /* Too small */
1911                                 for (y = y1; y < y2; y++)
1912                                 {
1913                                         for (x = x1; x < x2; x++)
1914                                         {
1915                                                 place_inner_bold(y, x);
1916                                         }
1917                                 }
1918                                 return;
1919                         }
1920
1921                         t1 = randint1(ysize - 2) + y1 + 1;
1922                         build_recursive_room(x1, y1, x2, t1, power - 2);
1923                         build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
1924                         break;
1925                 }
1926         }
1927 }
1928
1929
1930 /*
1931  * Add outer wall to a floored region
1932  * Note: no range checking is done so must be inside dungeon
1933  * This routine also stomps on doors
1934  */
1935 void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2)
1936 {
1937         cave_type *c_ptr;
1938         feature_type *f_ptr;
1939         int i, j;
1940
1941         if (!in_bounds(y, x)) return;
1942
1943         c_ptr = &cave[y][x];
1944
1945         /* hack- check to see if square has been visited before
1946         * if so, then exit (use room flag to do this) */
1947         if (c_ptr->info & CAVE_ROOM) return;
1948
1949         /* set room flag */
1950         c_ptr->info |= CAVE_ROOM;
1951
1952         f_ptr = &f_info[c_ptr->feat];
1953
1954         if (is_floor_bold(y, x))
1955         {
1956                 for (i = -1; i <= 1; i++)
1957                 {
1958                         for (j = -1; j <= 1; j++)
1959                         {
1960                                 if ((x + i >= x1) && (x + i <= x2) &&
1961                                          (y + j >= y1) && (y + j <= y2))
1962                                 {
1963                                         add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
1964                                         if (light) c_ptr->info |= CAVE_GLOW;
1965                                 }
1966                         }
1967                 }
1968         }
1969         else if (is_extra_bold(y, x))
1970         {
1971                 /* Set bounding walls */
1972                 place_outer_bold(y, x);
1973                 if (light) c_ptr->info |= CAVE_GLOW;
1974         }
1975         else if (permanent_wall(f_ptr))
1976         {
1977                 /* Set bounding walls */
1978                 if (light) c_ptr->info |= CAVE_GLOW;
1979         }
1980 }
1981
1982
1983 /*
1984  * Hacked distance formula - gives the 'wrong' answer.
1985  * Used to build crypts
1986  */
1987 int dist2(int x1, int y1, int x2, int y2, int h1, int h2, int h3, int h4)
1988 {
1989         int dx, dy;
1990         dx = abs(x2 - x1);
1991         dy = abs(y2 - y1);
1992
1993         /* Basically this works by taking the normal pythagorean formula
1994          * and using an expansion to express this in a way without the
1995          * square root.  This approximate formula is then perturbed to give
1996          * the distorted results.  (I found this by making a mistake when I was
1997          * trying to fix the circular rooms.)
1998          */
1999
2000         /* h1-h4 are constants that describe the metric */
2001         if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
2002         if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
2003         return (((dx + dy) * 128) / 181 +
2004                 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
2005         /* 128/181 is approx. 1/sqrt(2) */
2006 }
2007
2008
2009
2010
2011 /* Create a new floor room with optional light */
2012 void generate_room_floor(int y1, int x1, int y2, int x2, int light)
2013 {
2014         int y, x;
2015         
2016         cave_type *c_ptr;
2017
2018         for (y = y1; y <= y2; y++)
2019         {
2020                 for (x = x1; x <= x2; x++)
2021                 {
2022                         /* Point to grid */
2023                         c_ptr = &cave[y][x];
2024                         place_floor_grid(c_ptr);
2025                         c_ptr->info |= (CAVE_ROOM);
2026                         if (light) c_ptr->info |= (CAVE_GLOW);
2027                 }
2028         }
2029 }
2030
2031 void generate_fill_perm_bold(int y1, int x1, int y2, int x2)
2032 {
2033         int y, x;
2034
2035         for (y = y1; y <= y2; y++)
2036         {
2037                 for (x = x1; x <= x2; x++)
2038                 {
2039                         /* Point to grid */
2040                         place_inner_perm_bold(y, x);
2041                 }
2042         }
2043 }
2044
2045
2046 /*!
2047  * @brief 与えられた部屋型IDに応じて部屋の生成処理分岐を行い結果を返す / Attempt to build a room of the given type at the given block
2048  * @param type 部屋型ID
2049  * @note that we restrict the number of "crowded" rooms to reduce the chance of overflowing the monster list during level creation.
2050  * @return 部屋の精製に成功した場合 TRUE を返す。
2051  */
2052 static bool room_build(int typ)
2053 {
2054         /* Build a room */
2055         switch (typ)
2056         {
2057         /* Build an appropriate room */
2058         case ROOM_T_NORMAL:        return build_type1();
2059         case ROOM_T_OVERLAP:       return build_type2();
2060         case ROOM_T_CROSS:         return build_type3();
2061         case ROOM_T_INNER_FEAT:    return build_type4();
2062         case ROOM_T_NEST:          return build_type5();
2063         case ROOM_T_PIT:           return build_type6();
2064         case ROOM_T_LESSER_VAULT:  return build_type7();
2065         case ROOM_T_GREATER_VAULT: return build_type8();
2066         case ROOM_T_FRACAVE:       return build_type9();
2067         case ROOM_T_RANDOM_VAULT:  return build_type10();
2068         case ROOM_T_OVAL:          return build_type11();
2069         case ROOM_T_CRYPT:         return build_type12();
2070         case ROOM_T_TRAP_PIT:      return build_type13();
2071         case ROOM_T_TRAP:          return build_type14();
2072         case ROOM_T_GLASS:         return build_type15();
2073         case ROOM_T_ARCADE:        return build_type16();
2074         }
2075
2076         /* Paranoia */
2077         return FALSE;
2078 }
2079
2080 /*!
2081  * @brief 指定した部屋の生成確率を別の部屋に加算し、指定した部屋の生成率を0にする
2082  * @param dst 確率を移す先の部屋種ID
2083  * @param src 確率を与える元の部屋種ID
2084  */
2085 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0) 
2086
2087 /*!
2088  * @brief 部屋生成処理のメインルーチン(Sangbandを経由してOangbandからの実装を引用) / Generate rooms in dungeon.  Build bigger rooms at first. [from SAngband (originally from OAngband)]
2089  * @return 部屋生成に成功した場合 TRUE を返す。
2090  */
2091 bool generate_rooms(void)
2092 {
2093         int i;
2094         bool remain;
2095         int crowded = 0;
2096         int total_prob;
2097         int prob_list[ROOM_T_MAX];
2098         int rooms_built = 0;
2099         int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
2100         int level_index = MIN(10, div_round(dun_level, 10));
2101
2102         /* Number of each type of room on this level */
2103         s16b room_num[ROOM_T_MAX];
2104
2105         /* Limit number of rooms */
2106         int dun_rooms = DUN_ROOMS_MAX * area_size / 100;
2107
2108         /* Assume normal cave */
2109         room_info_type *room_info_ptr = room_info_normal;
2110
2111         /*
2112          * Initialize probability list.
2113          */
2114         for (i = 0; i < ROOM_T_MAX; i++)
2115         {
2116                 /* No rooms allowed above their minimum depth. */
2117                 if (dun_level < room_info_ptr[i].min_level)
2118                 {
2119                         prob_list[i] = 0;
2120                 }
2121                 else
2122                 {
2123                         prob_list[i] = room_info_ptr[i].prob[level_index];
2124                 }
2125         }
2126
2127         /*
2128          * XXX -- Various dungeon types and options.
2129          */
2130
2131         /*! @details ダンジョンにBEGINNER、CHAMELEON、SMALLESTいずれのフラグもなく、かつ「常に通常でない部屋を生成する」フラグがONならば、GRATER_VAULTのみを生成対象とする。 / Ironman sees only Greater Vaults */
2132         if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON | DF1_SMALLEST))))
2133         {
2134                 for (i = 0; i < ROOM_T_MAX; i++)
2135                 {
2136                         if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
2137                         else prob_list[i] = 0;
2138                 }
2139         }
2140
2141         /*! @details ダンジョンにNO_VAULTフラグがあるならば、LESSER_VAULT / GREATER_VAULT/ RANDOM_VAULTを除外 / Forbidden vaults */
2142         else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
2143         {
2144                 prob_list[ROOM_T_LESSER_VAULT] = 0;
2145                 prob_list[ROOM_T_GREATER_VAULT] = 0;
2146                 prob_list[ROOM_T_RANDOM_VAULT] = 0;
2147         }
2148
2149         /*! @details ダンジョンにNO_CAVEフラグがある場合、FRACAVEの生成枠がNORMALに与えられる。CRIPT、OVALの生成枠がINNER_Fに与えられる。/ NO_CAVE dungeon (Castle)*/
2150         if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
2151         {
2152                 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
2153                 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
2154                 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
2155         }
2156
2157         /*! @details ダンジョンにCAVEフラグがある場合、NORMALの生成枠がFRACAVEに与えられる。/ CAVE dungeon (Orc cave etc.) */
2158         else if (d_info[dungeon_type].flags1 & DF1_CAVE)
2159         {
2160                 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
2161         }
2162
2163         /*! @details ダンジョンの基本地形が最初から渓谷かアリーナ型の場合 FRACAVE は生成から除外。 /  No caves when a (random) cavern exists: they look bad */
2164         else if (dun->cavern || dun->empty_level)
2165         {
2166                 prob_list[ROOM_T_FRACAVE] = 0;
2167         }
2168
2169         /*! @details ダンジョンに最初からGLASS_ROOMフラグがある場合、GLASS を生成から除外。/ Forbidden glass rooms */
2170         if (!(d_info[dungeon_type].flags1 & DF1_GLASS_ROOM))
2171         {
2172                 prob_list[ROOM_T_GLASS] = 0;
2173         }
2174
2175         /*! @details ARCADEは同フラグがダンジョンにないと生成されない。 / Forbidden glass rooms */
2176         if (!(d_info[dungeon_type].flags1 & DF1_ARCADE))
2177         {
2178                 prob_list[ROOM_T_ARCADE] = 0;
2179         }
2180
2181         /*
2182          * Initialize number of rooms,
2183          * And calcurate total probability.
2184          */
2185         for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
2186         {
2187                 room_num[i] = 0;
2188                 total_prob += prob_list[i];
2189         }
2190
2191         /*
2192          * Prepare the number of rooms, of all types, we should build
2193          * on this level.
2194          */
2195         for (i = dun_rooms; i > 0; i--)
2196         {
2197                 int room_type;
2198                 int rand = randint0(total_prob);
2199
2200                 /* Get room_type randomly */
2201                 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
2202                 {
2203                         if (rand < prob_list[room_type]) break;
2204                         else rand -= prob_list[room_type];
2205                 }
2206
2207                 /* Paranoia */
2208                 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
2209
2210                 /* Increase the number of rooms of that type we should build. */
2211                 room_num[room_type]++;
2212
2213                 switch (room_type)
2214                 {
2215                 case ROOM_T_NEST:
2216                 case ROOM_T_PIT:
2217                 case ROOM_T_LESSER_VAULT:
2218                 case ROOM_T_TRAP_PIT:
2219                 case ROOM_T_GLASS:
2220                 case ROOM_T_ARCADE:
2221
2222                         /* Large room */
2223                         i -= 2;
2224                         break;
2225
2226                 case ROOM_T_GREATER_VAULT:
2227                 case ROOM_T_RANDOM_VAULT:
2228
2229                         /* Largest room */
2230                         i -= 3;
2231                         break;
2232                 }
2233         }
2234
2235         /*
2236          * Build each type of room one by one until we cannot build any more.
2237          * [from SAngband (originally from OAngband)]
2238          */
2239         while (TRUE)
2240         {
2241                 /* Assume no remaining rooms */
2242                 remain = FALSE;
2243
2244                 for (i = 0; i < ROOM_T_MAX; i++)
2245                 {
2246                         /* What type of room are we building now? */
2247                         int room_type = room_build_order[i];
2248
2249                         /* Go next if none available */
2250                         if (!room_num[room_type]) continue;
2251
2252                         /* Use up one unit */
2253                         room_num[room_type]--;
2254
2255                         /* Build the room. */
2256                         if (room_build(room_type))
2257                         {
2258                                 /* Increase the room built count. */
2259                                 rooms_built++;
2260
2261                                 /* Mark as there was some remaining rooms */
2262                                 remain = TRUE;
2263
2264                                 switch (room_type)
2265                                 {
2266                                 case ROOM_T_PIT:
2267                                 case ROOM_T_NEST:
2268                                 case ROOM_T_TRAP_PIT:
2269
2270                                         /* Avoid too many monsters */
2271                                         if (++crowded >= 2)
2272                                         {
2273                                                 room_num[ROOM_T_PIT] = 0;
2274                                                 room_num[ROOM_T_NEST] = 0;
2275                                                 room_num[ROOM_T_TRAP_PIT] = 0;
2276                                         }
2277                                         break;
2278
2279                                 case ROOM_T_ARCADE:
2280
2281                                         /* Avoid double-town */
2282                                         room_num[ROOM_T_ARCADE] = 0;
2283                                         break;
2284                                 }
2285                         }
2286                 }
2287
2288                 /* End loop if no room remain */
2289                 if (!remain) break;
2290         }
2291
2292         /*! @details 部屋生成数が2未満の場合生成失敗を返す */
2293         if (rooms_built < 2)
2294         {
2295                 msg_format_wizard(CHEAT_DUNGEON, _("部屋数が2未満でした。生成を再試行します。", "Number of rooms was under 2. Retry."), rooms_built);
2296                 return FALSE;
2297         }
2298
2299         msg_format_wizard(CHEAT_DUNGEON, _("このダンジョンの部屋数は %d です。", "Number of Rooms: %d"), rooms_built);
2300
2301         return TRUE;
2302 }