OSDN Git Service

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