OSDN Git Service

d4df861c6f5f6b6a4724ebe450da56f0b187aacc
[hengband/hengband.git] / src / rooms-vault.c
1 #include "angband.h"\r
2 #include "grid.h"\r
3 #include "rooms.h"\r
4 #include "generate.h"\r
5 #include "trap.h"\r
6 \r
7 /*\r
8 * This function creates a random vault that looks like a collection of bubbles.\r
9 * It works by getting a set of coordinates that represent the center of each\r
10 * bubble.  The entire room is made by seeing which bubble center is closest. If\r
11 * two centers are equidistant then the square is a wall, otherwise it is a floor.\r
12 * The only exception is for squares really near a center, these are always floor.\r
13 * (It looks better than without this check.)\r
14 *\r
15 * Note: If two centers are on the same point then this algorithm will create a\r
16 *       blank bubble filled with walls. - This is prevented from happening.\r
17 */\r
18 static void build_bubble_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
19 {\r
20 #define BUBBLENUM 10            /* number of bubbles */\r
21 \r
22         /* array of center points of bubbles */\r
23         coord center[BUBBLENUM];\r
24 \r
25         int i, j;\r
26         POSITION x, y;\r
27         u16b min1, min2, temp;\r
28         bool done;\r
29 \r
30         /* Offset from center to top left hand corner */\r
31         POSITION xhsize = xsize / 2;\r
32         POSITION yhsize = ysize / 2;\r
33 \r
34         msg_print_wizard(CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));\r
35 \r
36         /* Allocate center of bubbles */\r
37         center[0].x = (byte)randint1(xsize - 3) + 1;\r
38         center[0].y = (byte)randint1(ysize - 3) + 1;\r
39 \r
40         for (i = 1; i < BUBBLENUM; i++)\r
41         {\r
42                 done = FALSE;\r
43 \r
44                 /* get center and check to see if it is unique */\r
45                 while (!done)\r
46                 {\r
47                         done = TRUE;\r
48 \r
49                         x = randint1(xsize - 3) + 1;\r
50                         y = randint1(ysize - 3) + 1;\r
51 \r
52                         for (j = 0; j < i; j++)\r
53                         {\r
54                                 /* rough test to see if there is an overlap */\r
55                                 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;\r
56                         }\r
57                 }\r
58 \r
59                 center[i].x = (byte_hack)x;\r
60                 center[i].y = (byte_hack)y;\r
61         }\r
62 \r
63 \r
64         /* Top and bottom boundaries */\r
65         for (i = 0; i < xsize; i++)\r
66         {\r
67                 int side_x = x0 - xhsize + i;\r
68 \r
69                 place_outer_noperm_bold(y0 - yhsize + 0, side_x);\r
70                 cave[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);\r
71                 place_outer_noperm_bold(y0 - yhsize + ysize - 1, side_x);\r
72                 cave[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);\r
73         }\r
74 \r
75         /* Left and right boundaries */\r
76         for (i = 1; i < ysize - 1; i++)\r
77         {\r
78                 int side_y = y0 - yhsize + i;\r
79 \r
80                 place_outer_noperm_bold(side_y, x0 - xhsize + 0);\r
81                 cave[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);\r
82                 place_outer_noperm_bold(side_y, x0 - xhsize + xsize - 1);\r
83                 cave[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);\r
84         }\r
85 \r
86         /* Fill in middle with bubbles */\r
87         for (x = 1; x < xsize - 1; x++)\r
88         {\r
89                 for (y = 1; y < ysize - 1; y++)\r
90                 {\r
91                         /* Get distances to two closest centers */\r
92 \r
93                         min1 = (u16b)distance(x, y, center[0].x, center[0].y);\r
94                         min2 = (u16b)distance(x, y, center[1].x, center[1].y);\r
95 \r
96                         if (min1 > min2)\r
97                         {\r
98                                 /* swap if in wrong order */\r
99                                 temp = min1;\r
100                                 min1 = min2;\r
101                                 min2 = temp;\r
102                         }\r
103 \r
104                         /* Scan the rest */\r
105                         for (i = 2; i < BUBBLENUM; i++)\r
106                         {\r
107                                 temp = (u16b)distance(x, y, center[i].x, center[i].y);\r
108 \r
109                                 if (temp < min1)\r
110                                 {\r
111                                         /* smallest */\r
112                                         min2 = min1;\r
113                                         min1 = temp;\r
114                                 }\r
115                                 else if (temp < min2)\r
116                                 {\r
117                                         /* second smallest */\r
118                                         min2 = temp;\r
119                                 }\r
120                         }\r
121                         if (((min2 - min1) <= 2) && (!(min1 < 3)))\r
122                         {\r
123                                 /* Boundary at midpoint+ not at inner region of bubble */\r
124                                 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);\r
125                         }\r
126                         else\r
127                         {\r
128                                 /* middle of a bubble */\r
129                                 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);\r
130                         }\r
131 \r
132                         /* clean up rest of flags */\r
133                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);\r
134                 }\r
135         }\r
136 \r
137         /* Try to add some random doors */\r
138         for (i = 0; i < 500; i++)\r
139         {\r
140                 x = randint1(xsize - 3) - xhsize + x0 + 1;\r
141                 y = randint1(ysize - 3) - yhsize + y0 + 1;\r
142                 add_door(x, y);\r
143         }\r
144 \r
145         /* Fill with monsters and treasure, low difficulty */\r
146         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));\r
147 }\r
148 \r
149 /* Create a random vault that looks like a collection of overlapping rooms */\r
150 static void build_room_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
151 {\r
152         POSITION x1, x2, y1, y2, xhsize, yhsize;\r
153         int i;\r
154 \r
155         /* get offset from center */\r
156         xhsize = xsize / 2;\r
157         yhsize = ysize / 2;\r
158 \r
159         msg_print_wizard(CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));\r
160 \r
161         /* fill area so don't get problems with arena levels */\r
162         for (x1 = 0; x1 < xsize; x1++)\r
163         {\r
164                 POSITION x = x0 - xhsize + x1;\r
165 \r
166                 for (y1 = 0; y1 < ysize; y1++)\r
167                 {\r
168                         POSITION y = y0 - yhsize + y1;\r
169 \r
170                         place_extra_bold(y, x);\r
171                         cave[y][x].info &= (~CAVE_ICKY);\r
172                 }\r
173         }\r
174 \r
175         /* add ten random rooms */\r
176         for (i = 0; i < 10; i++)\r
177         {\r
178                 x1 = randint1(xhsize) * 2 + x0 - xhsize;\r
179                 x2 = randint1(xhsize) * 2 + x0 - xhsize;\r
180                 y1 = randint1(yhsize) * 2 + y0 - yhsize;\r
181                 y2 = randint1(yhsize) * 2 + y0 - yhsize;\r
182                 build_room(x1, x2, y1, y2);\r
183         }\r
184 \r
185         /* Add some random doors */\r
186         for (i = 0; i < 500; i++)\r
187         {\r
188                 x1 = randint1(xsize - 3) - xhsize + x0 + 1;\r
189                 y1 = randint1(ysize - 3) - yhsize + y0 + 1;\r
190                 add_door(x1, y1);\r
191         }\r
192 \r
193         /* Fill with monsters and treasure, high difficulty */\r
194         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);\r
195 }\r
196 \r
197 \r
198 /* Create a random vault out of a fractal cave */\r
199 static void build_cave_vault(POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)\r
200 {\r
201         int grd, roug, cutoff;\r
202         bool done, light, room;\r
203         POSITION xhsize, yhsize, xsize, ysize, x, y;\r
204 \r
205         /* round to make sizes even */\r
206         xhsize = xsiz / 2;\r
207         yhsize = ysiz / 2;\r
208         xsize = xhsize * 2;\r
209         ysize = yhsize * 2;\r
210 \r
211         msg_print_wizard(CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));\r
212 \r
213         light = done = FALSE;\r
214         room = TRUE;\r
215 \r
216         while (!done)\r
217         {\r
218                 /* testing values for these parameters feel free to adjust */\r
219                 grd = 1 << randint0(4);\r
220 \r
221                 /* want average of about 16 */\r
222                 roug = randint1(8) * randint1(4);\r
223 \r
224                 /* about size/2 */\r
225                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +\r
226                         randint1(xsize / 4) + randint1(ysize / 4);\r
227 \r
228                 /* make it */\r
229                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);\r
230 \r
231                 /* Convert to normal format+ clean up */\r
232                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);\r
233         }\r
234 \r
235         /* Set icky flag because is a vault */\r
236         for (x = 0; x <= xsize; x++)\r
237         {\r
238                 for (y = 0; y <= ysize; y++)\r
239                 {\r
240                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;\r
241                 }\r
242         }\r
243 \r
244         /* Fill with monsters and treasure, low difficulty */\r
245         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));\r
246 }\r
247 \r
248 \r
249 \r
250 /*!\r
251 * @brief Vault地形を回転、上下左右反転するための座標変換を返す / coordinate translation code\r
252 * @param x 変換したい点のX座標参照ポインタ\r
253 * @param y 変換したい点のY座標参照ポインタ\r
254 * @param xoffset Vault生成時の基準X座標\r
255 * @param yoffset Vault生成時の基準Y座標\r
256 * @param transno 処理ID\r
257 * @return なし\r
258 */\r
259 static void coord_trans(POSITION *x, POSITION *y, POSITION xoffset, POSITION yoffset, int transno)\r
260 {\r
261         int i;\r
262         int temp;\r
263 \r
264         /*\r
265         * transno specifies what transformation is required. (0-7)\r
266         * The lower two bits indicate by how much the vault is rotated,\r
267         * and the upper bit indicates a reflection.\r
268         * This is done by using rotation matrices... however since\r
269         * these are mostly zeros for rotations by 90 degrees this can\r
270         * be expressed simply in terms of swapping and inverting the\r
271         * x and y coordinates.\r
272         */\r
273         for (i = 0; i < transno % 4; i++)\r
274         {\r
275                 /* rotate by 90 degrees */\r
276                 temp = *x;\r
277                 *x = -(*y);\r
278                 *y = temp;\r
279         }\r
280 \r
281         if (transno / 4)\r
282         {\r
283                 /* Reflect depending on status of 3rd bit. */\r
284                 *x = -(*x);\r
285         }\r
286 \r
287         /* Add offsets so vault stays in the first quadrant */\r
288         *x += xoffset;\r
289         *y += yoffset;\r
290 }\r
291 \r
292 \r
293 /*!\r
294 * @brief Vaultをフロアに配置する / Hack -- fill in "vault" rooms\r
295 * @param yval 生成基準Y座標\r
296 * @param xval 生成基準X座標\r
297 * @param ymax VaultのYサイズ\r
298 * @param xmax VaultのXサイズ\r
299 * @param data Vaultのデータ文字列\r
300 * @param xoffset 変換基準X座標\r
301 * @param yoffset 変換基準Y座標\r
302 * @param transno 変換ID\r
303 * @return なし\r
304 */\r
305 static void build_vault(POSITION yval, POSITION xval, POSITION ymax, POSITION xmax, cptr data,\r
306         POSITION xoffset, POSITION yoffset, int transno)\r
307 {\r
308         POSITION dx, dy, x, y, i, j;\r
309         cptr t;\r
310         cave_type *c_ptr;\r
311 \r
312         /* Place dungeon features and objects */\r
313         for (t = data, dy = 0; dy < ymax; dy++)\r
314         {\r
315                 for (dx = 0; dx < xmax; dx++, t++)\r
316                 {\r
317                         /* prevent loop counter from being overwritten */\r
318                         i = dx;\r
319                         j = dy;\r
320 \r
321                         /* Flip / rotate */\r
322                         coord_trans(&i, &j, xoffset, yoffset, transno);\r
323 \r
324                         /* Extract the location */\r
325                         if (transno % 2 == 0)\r
326                         {\r
327                                 /* no swap of x/y */\r
328                                 x = xval - (xmax / 2) + i;\r
329                                 y = yval - (ymax / 2) + j;\r
330                         }\r
331                         else\r
332                         {\r
333                                 /* swap of x/y */\r
334                                 x = xval - (ymax / 2) + i;\r
335                                 y = yval - (xmax / 2) + j;\r
336                         }\r
337 \r
338                         /* Hack -- skip "non-grids" */\r
339                         if (*t == ' ') continue;\r
340 \r
341                         /* Access the grid */\r
342                         c_ptr = &cave[y][x];\r
343 \r
344                         /* Lay down a floor */\r
345                         place_floor_grid(c_ptr);\r
346 \r
347                         /* Remove any mimic */\r
348                         c_ptr->mimic = 0;\r
349 \r
350                         /* Part of a vault */\r
351                         c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);\r
352 \r
353                         /* Analyze the grid */\r
354                         switch (*t)\r
355                         {\r
356                                 /* Granite wall (outer) */\r
357                         case '%':\r
358                                 place_outer_noperm_grid(c_ptr);\r
359                                 break;\r
360 \r
361                                 /* Granite wall (inner) */\r
362                         case '#':\r
363                                 place_inner_grid(c_ptr);\r
364                                 break;\r
365 \r
366                                 /* Glass wall (inner) */\r
367                         case '$':\r
368                                 place_inner_grid(c_ptr);\r
369                                 c_ptr->feat = feat_glass_wall;\r
370                                 break;\r
371 \r
372                                 /* Permanent wall (inner) */\r
373                         case 'X':\r
374                                 place_inner_perm_grid(c_ptr);\r
375                                 break;\r
376 \r
377                                 /* Permanent glass wall (inner) */\r
378                         case 'Y':\r
379                                 place_inner_perm_grid(c_ptr);\r
380                                 c_ptr->feat = feat_permanent_glass_wall;\r
381                                 break;\r
382 \r
383                                 /* Treasure/trap */\r
384                         case '*':\r
385                                 if (randint0(100) < 75)\r
386                                 {\r
387                                         place_object(y, x, 0L);\r
388                                 }\r
389                                 else\r
390                                 {\r
391                                         place_trap(y, x);\r
392                                 }\r
393                                 break;\r
394 \r
395                                 /* Secret doors */\r
396                         case '+':\r
397                                 place_secret_door(y, x, DOOR_DEFAULT);\r
398                                 break;\r
399 \r
400                                 /* Secret glass doors */\r
401                         case '-':\r
402                                 place_secret_door(y, x, DOOR_GLASS_DOOR);\r
403                                 if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;\r
404                                 break;\r
405 \r
406                                 /* Curtains */\r
407                         case '\'':\r
408                                 place_secret_door(y, x, DOOR_CURTAIN);\r
409                                 break;\r
410 \r
411                                 /* Trap */\r
412                         case '^':\r
413                                 place_trap(y, x);\r
414                                 break;\r
415 \r
416                                 /* Black market in a dungeon */\r
417                         case 'S':\r
418                                 set_cave_feat(y, x, feat_black_market);\r
419                                 store_init(NO_TOWN, STORE_BLACK);\r
420                                 break;\r
421 \r
422                                 /* The Pattern */\r
423                         case 'p':\r
424                                 set_cave_feat(y, x, feat_pattern_start);\r
425                                 break;\r
426 \r
427                         case 'a':\r
428                                 set_cave_feat(y, x, feat_pattern_1);\r
429                                 break;\r
430 \r
431                         case 'b':\r
432                                 set_cave_feat(y, x, feat_pattern_2);\r
433                                 break;\r
434 \r
435                         case 'c':\r
436                                 set_cave_feat(y, x, feat_pattern_3);\r
437                                 break;\r
438 \r
439                         case 'd':\r
440                                 set_cave_feat(y, x, feat_pattern_4);\r
441                                 break;\r
442 \r
443                         case 'P':\r
444                                 set_cave_feat(y, x, feat_pattern_end);\r
445                                 break;\r
446 \r
447                         case 'B':\r
448                                 set_cave_feat(y, x, feat_pattern_exit);\r
449                                 break;\r
450 \r
451                         case 'A':\r
452                                 /* Reward for Pattern walk */\r
453                                 object_level = base_level + 12;\r
454                                 place_object(y, x, AM_GOOD | AM_GREAT);\r
455                                 object_level = base_level;\r
456                                 break;\r
457 \r
458                         case '~':\r
459                                 set_cave_feat(y, x, feat_shallow_water);\r
460                                 break;\r
461 \r
462                         case '=':\r
463                                 set_cave_feat(y, x, feat_deep_water);\r
464                                 break;\r
465 \r
466                         case 'v':\r
467                                 set_cave_feat(y, x, feat_shallow_lava);\r
468                                 break;\r
469 \r
470                         case 'w':\r
471                                 set_cave_feat(y, x, feat_deep_lava);\r
472                                 break;\r
473 \r
474                         }\r
475                 }\r
476         }\r
477 \r
478 \r
479         /* Place dungeon monsters and objects */\r
480         for (t = data, dy = 0; dy < ymax; dy++)\r
481         {\r
482                 for (dx = 0; dx < xmax; dx++, t++)\r
483                 {\r
484                         /* prevent loop counter from being overwritten */\r
485                         i = dx;\r
486                         j = dy;\r
487 \r
488                         /* Flip / rotate */\r
489                         coord_trans(&i, &j, xoffset, yoffset, transno);\r
490 \r
491                         /* Extract the location */\r
492                         if (transno % 2 == 0)\r
493                         {\r
494                                 /* no swap of x/y */\r
495                                 x = xval - (xmax / 2) + i;\r
496                                 y = yval - (ymax / 2) + j;\r
497                         }\r
498                         else\r
499                         {\r
500                                 /* swap of x/y */\r
501                                 x = xval - (ymax / 2) + i;\r
502                                 y = yval - (xmax / 2) + j;\r
503                         }\r
504 \r
505                         /* Hack -- skip "non-grids" */\r
506                         if (*t == ' ') continue;\r
507 \r
508                         /* Analyze the symbol */\r
509                         switch (*t)\r
510                         {\r
511                                 /* Monster */\r
512                         case '&':\r
513                         {\r
514                                 monster_level = base_level + 5;\r
515                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));\r
516                                 monster_level = base_level;\r
517                                 break;\r
518                         }\r
519 \r
520                         /* Meaner monster */\r
521                         case '@':\r
522                         {\r
523                                 monster_level = base_level + 11;\r
524                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));\r
525                                 monster_level = base_level;\r
526                                 break;\r
527                         }\r
528 \r
529                         /* Meaner monster, plus treasure */\r
530                         case '9':\r
531                         {\r
532                                 monster_level = base_level + 9;\r
533                                 place_monster(y, x, PM_ALLOW_SLEEP);\r
534                                 monster_level = base_level;\r
535                                 object_level = base_level + 7;\r
536                                 place_object(y, x, AM_GOOD);\r
537                                 object_level = base_level;\r
538                                 break;\r
539                         }\r
540 \r
541                         /* Nasty monster and treasure */\r
542                         case '8':\r
543                         {\r
544                                 monster_level = base_level + 40;\r
545                                 place_monster(y, x, PM_ALLOW_SLEEP);\r
546                                 monster_level = base_level;\r
547                                 object_level = base_level + 20;\r
548                                 place_object(y, x, AM_GOOD | AM_GREAT);\r
549                                 object_level = base_level;\r
550                                 break;\r
551                         }\r
552 \r
553                         /* Monster and/or object */\r
554                         case ',':\r
555                         {\r
556                                 if (randint0(100) < 50)\r
557                                 {\r
558                                         monster_level = base_level + 3;\r
559                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));\r
560                                         monster_level = base_level;\r
561                                 }\r
562                                 if (randint0(100) < 50)\r
563                                 {\r
564                                         object_level = base_level + 7;\r
565                                         place_object(y, x, 0L);\r
566                                         object_level = base_level;\r
567                                 }\r
568                                 break;\r
569                         }\r
570 \r
571                         }\r
572                 }\r
573         }\r
574 }\r
575 \r
576 \r
577 \r
578 /*!\r
579 * @brief タイプ7の部屋…v_info.txtより小型vaultを生成する / Type 7 -- simple vaults (see "v_info.txt")\r
580 * @return なし\r
581 */\r
582 bool build_type7(void)\r
583 {\r
584         vault_type *v_ptr = NULL;\r
585         int dummy;\r
586         POSITION x, y;\r
587         POSITION xval, yval;\r
588         POSITION xoffset, yoffset;\r
589         int transno;\r
590 \r
591         /* Pick a lesser vault */\r
592         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)\r
593         {\r
594                 /* Access a random vault record */\r
595                 v_ptr = &v_info[randint0(max_v_idx)];\r
596 \r
597                 /* Accept the first lesser vault */\r
598                 if (v_ptr->typ == 7) break;\r
599         }\r
600 \r
601         /* No lesser vault found */\r
602         if (dummy >= SAFE_MAX_ATTEMPTS)\r
603         {\r
604                 msg_print_wizard(CHEAT_DUNGEON, _("小型固定Vaultを配置できませんでした。", "Could not place lesser vault."));\r
605                 return FALSE;\r
606         }\r
607 \r
608         /* pick type of transformation (0-7) */\r
609         transno = randint0(8);\r
610 \r
611         /* calculate offsets */\r
612         x = v_ptr->wid;\r
613         y = v_ptr->hgt;\r
614 \r
615         /* Some huge vault cannot be ratated to fit in the dungeon */\r
616         if (x + 2 > cur_hgt - 2)\r
617         {\r
618                 /* Forbid 90 or 270 degree ratation */\r
619                 transno &= ~1;\r
620         }\r
621 \r
622         coord_trans(&x, &y, 0, 0, transno);\r
623 \r
624         if (x < 0)\r
625         {\r
626                 xoffset = -x - 1;\r
627         }\r
628         else\r
629         {\r
630                 xoffset = 0;\r
631         }\r
632 \r
633         if (y < 0)\r
634         {\r
635                 yoffset = -y - 1;\r
636         }\r
637         else\r
638         {\r
639                 yoffset = 0;\r
640         }\r
641 \r
642         /* Find and reserve some space in the dungeon.  Get center of room. */\r
643         if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;\r
644 \r
645 #ifdef FORCE_V_IDX\r
646         v_ptr = &v_info[2];\r
647 #endif\r
648 \r
649         msg_format_wizard(CHEAT_DUNGEON, _("小型Vault(%s)を生成しました。", "Lesser vault (%s)."), v_name + v_ptr->name);\r
650 \r
651         /* Hack -- Build the vault */\r
652         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,\r
653                 v_text + v_ptr->text, xoffset, yoffset, transno);\r
654 \r
655         return TRUE;\r
656 }\r
657 \r
658 /*!\r
659 * @brief タイプ8の部屋…v_info.txtより大型vaultを生成する / Type 8 -- greater vaults (see "v_info.txt")\r
660 * @return なし\r
661 */\r
662 bool build_type8(void)\r
663 {\r
664         vault_type *v_ptr;\r
665         int dummy;\r
666         POSITION xval, yval;\r
667         POSITION x, y;\r
668         int transno;\r
669         POSITION xoffset, yoffset;\r
670 \r
671         /* Pick a greater vault */\r
672         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)\r
673         {\r
674                 /* Access a random vault record */\r
675                 v_ptr = &v_info[randint0(max_v_idx)];\r
676 \r
677                 /* Accept the first greater vault */\r
678                 if (v_ptr->typ == 8) break;\r
679         }\r
680 \r
681         /* No greater vault found */\r
682         if (dummy >= SAFE_MAX_ATTEMPTS)\r
683         {\r
684                 msg_print_wizard(CHEAT_DUNGEON, _("大型固定Vaultを配置できませんでした。", "Could not place greater vault."));\r
685                 return FALSE;\r
686         }\r
687 \r
688         /* pick type of transformation (0-7) */\r
689         transno = randint0(8);\r
690 \r
691         /* calculate offsets */\r
692         x = v_ptr->wid;\r
693         y = v_ptr->hgt;\r
694 \r
695         /* Some huge vault cannot be ratated to fit in the dungeon */\r
696         if (x + 2 > cur_hgt - 2)\r
697         {\r
698                 /* Forbid 90 or 270 degree ratation */\r
699                 transno &= ~1;\r
700         }\r
701 \r
702         coord_trans(&x, &y, 0, 0, transno);\r
703 \r
704         if (x < 0)\r
705         {\r
706                 xoffset = -x - 1;\r
707         }\r
708         else\r
709         {\r
710                 xoffset = 0;\r
711         }\r
712 \r
713         if (y < 0)\r
714         {\r
715                 yoffset = -y - 1;\r
716         }\r
717         else\r
718         {\r
719                 yoffset = 0;\r
720         }\r
721 \r
722         /*\r
723         * Try to allocate space for room.  If fails, exit\r
724         *\r
725         * Hack -- Prepare a bit larger space (+2, +2) to\r
726         * prevent generation of vaults with no-entrance.\r
727         */\r
728         /* Find and reserve some space in the dungeon.  Get center of room. */\r
729         if (!find_space(&yval, &xval, (POSITION)(abs(y) + 2), (POSITION)(abs(x) + 2))) return FALSE;\r
730 \r
731 #ifdef FORCE_V_IDX\r
732         v_ptr = &v_info[76 + randint1(3)];\r
733 #endif\r
734 \r
735         msg_format_wizard(CHEAT_DUNGEON, _("大型固定Vault(%s)を生成しました。", "Greater vault (%s)."), v_name + v_ptr->name);\r
736 \r
737         /* Hack -- Build the vault */\r
738         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,\r
739                 v_text + v_ptr->text, xoffset, yoffset, transno);\r
740 \r
741         return TRUE;\r
742 }\r
743 \r
744 \r
745 /*\r
746 * Build target vault.\r
747 * This is made by two concentric "crypts" with perpendicular\r
748 * walls creating the cross-hairs.\r
749 */\r
750 static void build_target_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
751 {\r
752         POSITION rad, x, y;\r
753 \r
754         /* Make a random metric */\r
755         POSITION h1, h2, h3, h4;\r
756         h1 = randint1(32) - 16;\r
757         h2 = randint1(16);\r
758         h3 = randint1(32);\r
759         h4 = randint1(32) - 16;\r
760 \r
761         msg_print_wizard(CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));\r
762 \r
763         /* work out outer radius */\r
764         if (xsize > ysize)\r
765         {\r
766                 rad = ysize / 2;\r
767         }\r
768         else\r
769         {\r
770                 rad = xsize / 2;\r
771         }\r
772 \r
773         /* Make floor */\r
774         for (x = x0 - rad; x <= x0 + rad; x++)\r
775         {\r
776                 for (y = y0 - rad; y <= y0 + rad; y++)\r
777                 {\r
778                         /* clear room flag */\r
779                         cave[y][x].info &= ~(CAVE_ROOM);\r
780 \r
781                         /* Vault - so is "icky" */\r
782                         cave[y][x].info |= CAVE_ICKY;\r
783 \r
784                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)\r
785                         {\r
786                                 /* inside- so is floor */\r
787                                 place_floor_bold(y, x);\r
788                         }\r
789                         else\r
790                         {\r
791                                 /* make granite outside so arena works */\r
792                                 place_extra_bold(y, x);\r
793                         }\r
794 \r
795                         /* proper boundary for arena */\r
796                         if (((y + rad) == y0) || ((y - rad) == y0) ||\r
797                                 ((x + rad) == x0) || ((x - rad) == x0))\r
798                         {\r
799                                 place_extra_bold(y, x);\r
800                         }\r
801                 }\r
802         }\r
803 \r
804         /* Find visible outer walls and set to be FEAT_OUTER */\r
805         add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,\r
806                 x0 + rad + 1, y0 + rad + 1);\r
807 \r
808         /* Add inner wall */\r
809         for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)\r
810         {\r
811                 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)\r
812                 {\r
813                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)\r
814                         {\r
815                                 /* Make an internal wall */\r
816                                 place_inner_bold(y, x);\r
817                         }\r
818                 }\r
819         }\r
820 \r
821         /* Add perpendicular walls */\r
822         for (x = x0 - rad; x <= x0 + rad; x++)\r
823         {\r
824                 place_inner_bold(y0, x);\r
825         }\r
826 \r
827         for (y = y0 - rad; y <= y0 + rad; y++)\r
828         {\r
829                 place_inner_bold(y, x0);\r
830         }\r
831 \r
832         /* Make inner vault */\r
833         for (y = y0 - 1; y <= y0 + 1; y++)\r
834         {\r
835                 place_inner_bold(y, x0 - 1);\r
836                 place_inner_bold(y, x0 + 1);\r
837         }\r
838         for (x = x0 - 1; x <= x0 + 1; x++)\r
839         {\r
840                 place_inner_bold(y0 - 1, x);\r
841                 place_inner_bold(y0 + 1, x);\r
842         }\r
843 \r
844         place_floor_bold(y0, x0);\r
845 \r
846 \r
847         /* Add doors to vault */\r
848         /* get two distances so can place doors relative to centre */\r
849         x = (rad - 2) / 4 + 1;\r
850         y = rad / 2 + x;\r
851 \r
852         add_door(x0 + x, y0);\r
853         add_door(x0 + y, y0);\r
854         add_door(x0 - x, y0);\r
855         add_door(x0 - y, y0);\r
856         add_door(x0, y0 + x);\r
857         add_door(x0, y0 + y);\r
858         add_door(x0, y0 - x);\r
859         add_door(x0, y0 - y);\r
860 \r
861         /* Fill with stuff - medium difficulty */\r
862         fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);\r
863 }\r
864 \r
865 \r
866 #ifdef ALLOW_CAVERNS_AND_LAKES\r
867 /*\r
868 * This routine uses a modified version of the lake code to make a\r
869 * distribution of some terrain type over the vault.  This type\r
870 * depends on the dungeon depth.\r
871 *\r
872 * Miniture rooms are then scattered across the vault.\r
873 */\r
874 static void build_elemental_vault(POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)\r
875 {\r
876         int grd, roug;\r
877         int c1, c2, c3;\r
878         bool done = FALSE;\r
879         POSITION xsize, ysize, xhsize, yhsize, x, y;\r
880         int i;\r
881         int type;\r
882 \r
883         msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));\r
884 \r
885         /* round to make sizes even */\r
886         xhsize = xsiz / 2;\r
887         yhsize = ysiz / 2;\r
888         xsize = xhsize * 2;\r
889         ysize = yhsize * 2;\r
890 \r
891         if (dun_level < 25)\r
892         {\r
893                 /* Earth vault  (Rubble) */\r
894                 type = LAKE_T_EARTH_VAULT;\r
895         }\r
896         else if (dun_level < 50)\r
897         {\r
898                 /* Air vault (Trees) */\r
899                 type = LAKE_T_AIR_VAULT;\r
900         }\r
901         else if (dun_level < 75)\r
902         {\r
903                 /* Water vault (shallow water) */\r
904                 type = LAKE_T_WATER_VAULT;\r
905         }\r
906         else\r
907         {\r
908                 /* Fire vault (shallow lava) */\r
909                 type = LAKE_T_FIRE_VAULT;\r
910         }\r
911 \r
912         while (!done)\r
913         {\r
914                 /* testing values for these parameters: feel free to adjust */\r
915                 grd = 1 << (randint0(3));\r
916 \r
917                 /* want average of about 16 */\r
918                 roug = randint1(8) * randint1(4);\r
919 \r
920                 /* Make up size of various componants */\r
921                 /* Floor */\r
922                 c3 = 2 * xsize / 3;\r
923 \r
924                 /* Deep water/lava */\r
925                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;\r
926 \r
927                 /* Shallow boundary */\r
928                 c2 = (c1 + c3) / 2;\r
929 \r
930                 /* make it */\r
931                 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);\r
932 \r
933                 /* Convert to normal format+ clean up */\r
934                 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);\r
935         }\r
936 \r
937         /* Set icky flag because is a vault */\r
938         for (x = 0; x <= xsize; x++)\r
939         {\r
940                 for (y = 0; y <= ysize; y++)\r
941                 {\r
942                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;\r
943                 }\r
944         }\r
945 \r
946         /* make a few rooms in the vault */\r
947         for (i = 1; i <= (xsize * ysize) / 50; i++)\r
948         {\r
949                 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,\r
950                         y0 + randint0(ysize - 4) - ysize / 2 + 2);\r
951         }\r
952 \r
953         /* Fill with monsters and treasure, low difficulty */\r
954         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,\r
955                 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));\r
956 }\r
957 #endif /* ALLOW_CAVERNS_AND_LAKES */\r
958 \r
959 \r
960 /* Build a "mini" checkerboard vault\r
961 *\r
962 * This is done by making a permanent wall maze and setting\r
963 * the diagonal sqaures of the checker board to be granite.\r
964 * The vault has two entrances on opposite sides to guarantee\r
965 * a way to get in even if the vault abuts a side of the dungeon.\r
966 */\r
967 static void build_mini_c_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
968 {\r
969         POSITION dy, dx;\r
970         POSITION y1, x1, y2, x2, y, x, total;\r
971         int m, n, num_vertices;\r
972         int *visited;\r
973 \r
974         msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));\r
975 \r
976         /* Pick a random room size */\r
977         dy = ysize / 2 - 1;\r
978         dx = xsize / 2 - 1;\r
979 \r
980         y1 = y0 - dy;\r
981         x1 = x0 - dx;\r
982         y2 = y0 + dy;\r
983         x2 = x0 + dx;\r
984 \r
985 \r
986         /* generate the room */\r
987         for (x = x1 - 2; x <= x2 + 2; x++)\r
988         {\r
989                 if (!in_bounds(y1 - 2, x)) break;\r
990 \r
991                 cave[y1 - 2][x].info |= (CAVE_ROOM | CAVE_ICKY);\r
992 \r
993                 place_outer_noperm_bold(y1 - 2, x);\r
994         }\r
995 \r
996         for (x = x1 - 2; x <= x2 + 2; x++)\r
997         {\r
998                 if (!in_bounds(y2 + 2, x)) break;\r
999 \r
1000                 cave[y2 + 2][x].info |= (CAVE_ROOM | CAVE_ICKY);\r
1001 \r
1002                 place_outer_noperm_bold(y2 + 2, x);\r
1003         }\r
1004 \r
1005         for (y = y1 - 2; y <= y2 + 2; y++)\r
1006         {\r
1007                 if (!in_bounds(y, x1 - 2)) break;\r
1008 \r
1009                 cave[y][x1 - 2].info |= (CAVE_ROOM | CAVE_ICKY);\r
1010 \r
1011                 place_outer_noperm_bold(y, x1 - 2);\r
1012         }\r
1013 \r
1014         for (y = y1 - 2; y <= y2 + 2; y++)\r
1015         {\r
1016                 if (!in_bounds(y, x2 + 2)) break;\r
1017 \r
1018                 cave[y][x2 + 2].info |= (CAVE_ROOM | CAVE_ICKY);\r
1019 \r
1020                 place_outer_noperm_bold(y, x2 + 2);\r
1021         }\r
1022 \r
1023         for (y = y1 - 1; y <= y2 + 1; y++)\r
1024         {\r
1025                 for (x = x1 - 1; x <= x2 + 1; x++)\r
1026                 {\r
1027                         cave_type *c_ptr = &cave[y][x];\r
1028 \r
1029                         c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);\r
1030 \r
1031                         /* Permanent walls */\r
1032                         place_inner_perm_grid(c_ptr);\r
1033                 }\r
1034         }\r
1035 \r
1036 \r
1037         /* dimensions of vertex array */\r
1038         m = dx + 1;\r
1039         n = dy + 1;\r
1040         num_vertices = m * n;\r
1041 \r
1042         /* initialize array of visited vertices */\r
1043         C_MAKE(visited, num_vertices, int);\r
1044 \r
1045         /* traverse the graph to create a spannng tree, pick a random root */\r
1046         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);\r
1047 \r
1048         /* Make it look like a checker board vault */\r
1049         for (x = x1; x <= x2; x++)\r
1050         {\r
1051                 for (y = y1; y <= y2; y++)\r
1052                 {\r
1053                         total = x - x1 + y - y1;\r
1054                         /* If total is odd- and is a floor then make a wall */\r
1055                         if ((total % 2 == 1) && is_floor_bold(y, x))\r
1056                         {\r
1057                                 place_inner_bold(y, x);\r
1058                         }\r
1059                 }\r
1060         }\r
1061 \r
1062         /* Make a couple of entrances */\r
1063         if (one_in_(2))\r
1064         {\r
1065                 /* left and right */\r
1066                 y = randint1(dy) + dy / 2;\r
1067                 place_inner_bold(y1 + y, x1 - 1);\r
1068                 place_inner_bold(y1 + y, x2 + 1);\r
1069         }\r
1070         else\r
1071         {\r
1072                 /* top and bottom */\r
1073                 x = randint1(dx) + dx / 2;\r
1074                 place_inner_bold(y1 - 1, x1 + x);\r
1075                 place_inner_bold(y2 + 1, x1 + x);\r
1076         }\r
1077 \r
1078         /* Fill with monsters and treasure, highest difficulty */\r
1079         fill_treasure(x1, x2, y1, y2, 10);\r
1080 \r
1081         C_KILL(visited, num_vertices, int);\r
1082 }\r
1083 \r
1084 /* Build a castle */\r
1085 /* Driver routine: clear the region and call the recursive\r
1086 * room routine.\r
1087 *\r
1088 *This makes a vault that looks like a castle/ city in the dungeon.\r
1089 */\r
1090 static void build_castle_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
1091 {\r
1092         POSITION dy, dx;\r
1093         POSITION y1, x1, y2, x2;\r
1094         POSITION y, x;\r
1095 \r
1096         /* Pick a random room size */\r
1097         dy = ysize / 2 - 1;\r
1098         dx = xsize / 2 - 1;\r
1099 \r
1100         y1 = y0 - dy;\r
1101         x1 = x0 - dx;\r
1102         y2 = y0 + dy;\r
1103         x2 = x0 + dx;\r
1104 \r
1105         msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));\r
1106 \r
1107         /* generate the room */\r
1108         for (y = y1 - 1; y <= y2 + 1; y++)\r
1109         {\r
1110                 for (x = x1 - 1; x <= x2 + 1; x++)\r
1111                 {\r
1112                         cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);\r
1113                         /* Make everything a floor */\r
1114                         place_floor_bold(y, x);\r
1115                 }\r
1116         }\r
1117 \r
1118         /* Make the castle */\r
1119         build_recursive_room(x1, y1, x2, y2, randint1(5));\r
1120 \r
1121         /* Fill with monsters and treasure, low difficulty */\r
1122         fill_treasure(x1, x2, y1, y2, randint1(3));\r
1123 }\r
1124 \r
1125 \r
1126 \r
1127 /*!\r
1128 * @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults\r
1129 * @return なし\r
1130 */\r
1131 bool build_type10(void)\r
1132 {\r
1133         POSITION y0, x0, xsize, ysize, vtype;\r
1134 \r
1135         /* big enough to look good, small enough to be fairly common. */\r
1136         xsize = randint1(22) + 22;\r
1137         ysize = randint1(11) + 11;\r
1138 \r
1139         /* Find and reserve some space in the dungeon.  Get center of room. */\r
1140         if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;\r
1141 \r
1142         /* Select type of vault */\r
1143 #ifdef ALLOW_CAVERNS_AND_LAKES\r
1144         do\r
1145         {\r
1146                 vtype = randint1(15);\r
1147         } while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&\r
1148                 ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));\r
1149 #else /* ALLOW_CAVERNS_AND_LAKES */\r
1150         do\r
1151         {\r
1152                 vtype = randint1(7);\r
1153         } while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&\r
1154                 ((vtype == 1) || (vtype == 3)));\r
1155 #endif /* ALLOW_CAVERNS_AND_LAKES */\r
1156 \r
1157         switch (vtype)\r
1158         {\r
1159                 /* Build an appropriate room */\r
1160         case 1: case  9: build_bubble_vault(x0, y0, xsize, ysize); break;\r
1161         case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;\r
1162         case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;\r
1163         case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;\r
1164         case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;\r
1165         case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;\r
1166         case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;\r
1167 #ifdef ALLOW_CAVERNS_AND_LAKES\r
1168         case 8: build_elemental_vault(x0, y0, xsize, ysize); break;\r
1169 #endif /* ALLOW_CAVERNS_AND_LAKES */\r
1170                 /* I know how to add a few more... give me some time. */\r
1171 \r
1172                 /* Paranoia */\r
1173         default: return FALSE;\r
1174         }\r
1175 \r
1176         return TRUE;\r
1177 }\r
1178 \r
1179 \r
1180 /*!\r
1181 * @brief タイプ16の部屋…v_info.txtより固定特殊部屋を生成する / Type 16 -- fixed special room (see "v_info.txt")\r
1182 * @return なし\r
1183 */\r
1184 bool build_type17(void)\r
1185 {\r
1186         vault_type *v_ptr = NULL;\r
1187         int dummy;\r
1188         POSITION x, y;\r
1189         POSITION xval, yval;\r
1190         POSITION xoffset, yoffset;\r
1191         int transno;\r
1192 \r
1193         /* Pick a lesser vault */\r
1194         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)\r
1195         {\r
1196                 /* Access a random vault record */\r
1197                 v_ptr = &v_info[randint0(max_v_idx)];\r
1198 \r
1199                 /* Accept the first lesser vault */\r
1200                 if (v_ptr->typ == 16) break;\r
1201         }\r
1202 \r
1203         /* No lesser vault found */\r
1204         if (dummy >= SAFE_MAX_ATTEMPTS)\r
1205         {\r
1206                 msg_print_wizard(CHEAT_DUNGEON, _("固定特殊部屋を配置できませんでした。", "Could not place fixed special room."));\r
1207                 return FALSE;\r
1208         }\r
1209 \r
1210         /* pick type of transformation (0-7) */\r
1211         transno = randint0(8);\r
1212 \r
1213         /* calculate offsets */\r
1214         x = v_ptr->wid;\r
1215         y = v_ptr->hgt;\r
1216 \r
1217         /* Some huge vault cannot be ratated to fit in the dungeon */\r
1218         if (x + 2 > cur_hgt - 2)\r
1219         {\r
1220                 /* Forbid 90 or 270 degree ratation */\r
1221                 transno &= ~1;\r
1222         }\r
1223 \r
1224         coord_trans(&x, &y, 0, 0, transno);\r
1225 \r
1226         if (x < 0)\r
1227         {\r
1228                 xoffset = -x - 1;\r
1229         }\r
1230         else\r
1231         {\r
1232                 xoffset = 0;\r
1233         }\r
1234 \r
1235         if (y < 0)\r
1236         {\r
1237                 yoffset = -y - 1;\r
1238         }\r
1239         else\r
1240         {\r
1241                 yoffset = 0;\r
1242         }\r
1243 \r
1244         /* Find and reserve some space in the dungeon.  Get center of room. */\r
1245         if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;\r
1246 \r
1247 #ifdef FORCE_V_IDX\r
1248         v_ptr = &v_info[2];\r
1249 #endif\r
1250 \r
1251         msg_format_wizard(CHEAT_DUNGEON, _("特殊固定部屋(%s)を生成しました。", "Special Fix room (%s)."), v_name + v_ptr->name);\r
1252 \r
1253         /* Hack -- Build the vault */\r
1254         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,\r
1255                 v_text + v_ptr->text, xoffset, yoffset, transno);\r
1256 \r
1257         return TRUE;\r
1258 }\r
1259 \r