OSDN Git Service

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