OSDN Git Service

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