OSDN Git Service

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