… | |
… | |
28 | #include <rproto.h> |
28 | #include <rproto.h> |
29 | #include <sproto.h> |
29 | #include <sproto.h> |
30 | |
30 | |
31 | #define CEDE coroapi::cede_to_tick (); rndm.seed (RP->random_seed + __LINE__); |
31 | #define CEDE coroapi::cede_to_tick (); rndm.seed (RP->random_seed + __LINE__); |
32 | |
32 | |
33 | static void symmetrize_layout (Maze maze, random_map_params *RP); |
33 | static void symmetrize_layout (Layout maze, random_map_params *RP); |
34 | static void rotate_layout (Maze maze, int rotation); |
34 | static void rotate_layout (Layout maze, int rotation); |
35 | |
35 | |
36 | void |
36 | void |
37 | dump_layout (char **layout, random_map_params *RP) |
37 | dump_layout (Layout layout) |
38 | { |
38 | { |
39 | { |
39 | for (int i = 0; i < layout->w; i++) |
40 | int i, j; |
|
|
41 | |
|
|
42 | for (i = 0; i < RP->Xsize; i++) |
|
|
43 | { |
40 | { |
44 | for (j = 0; j < RP->Ysize; j++) |
41 | for (int j = 0; j < layout->h; j++) |
45 | { |
42 | putc (layout[i][j] ? layout[i][j] : ' ', stdout); |
46 | if (layout[i][j] == 0) |
43 | |
47 | layout[i][j] = ' '; |
44 | putc ('\n', stdout); |
48 | printf ("%c", layout[i][j]); |
|
|
49 | if (layout[i][j] == ' ') |
|
|
50 | layout[i][j] = 0; |
|
|
51 | } |
|
|
52 | printf ("\n"); |
|
|
53 | } |
45 | } |
54 | } |
46 | |
55 | printf ("\n"); |
47 | putc ('\n', stdout); |
56 | } |
48 | } |
57 | |
49 | |
58 | bool |
50 | bool |
59 | maptile::generate_random_map (random_map_params *RP) |
51 | maptile::generate_random_map (random_map_params *RP) |
60 | { |
52 | { |
… | |
… | |
115 | * the numeric layoutstyle, so there is only one area that actually |
107 | * the numeric layoutstyle, so there is only one area that actually |
116 | * calls the code to make the maps. |
108 | * calls the code to make the maps. |
117 | */ |
109 | */ |
118 | if (strstr (RP->layoutstyle, "onion")) |
110 | if (strstr (RP->layoutstyle, "onion")) |
119 | RP->map_layout_style = LAYOUT_ONION; |
111 | RP->map_layout_style = LAYOUT_ONION; |
120 | |
|
|
121 | if (strstr (RP->layoutstyle, "maze")) |
112 | else if (strstr (RP->layoutstyle, "maze")) |
122 | RP->map_layout_style = LAYOUT_MAZE; |
113 | RP->map_layout_style = LAYOUT_MAZE; |
123 | |
|
|
124 | if (strstr (RP->layoutstyle, "spiral")) |
114 | else if (strstr (RP->layoutstyle, "spiral")) |
125 | RP->map_layout_style = LAYOUT_SPIRAL; |
115 | RP->map_layout_style = LAYOUT_SPIRAL; |
126 | |
|
|
127 | if (strstr (RP->layoutstyle, "rogue")) |
116 | else if (strstr (RP->layoutstyle, "rogue")) |
128 | RP->map_layout_style = LAYOUT_ROGUELIKE; |
117 | RP->map_layout_style = LAYOUT_ROGUELIKE; |
129 | |
|
|
130 | if (strstr (RP->layoutstyle, "snake")) |
118 | else if (strstr (RP->layoutstyle, "snake")) |
131 | RP->map_layout_style = LAYOUT_SNAKE; |
119 | RP->map_layout_style = LAYOUT_SNAKE; |
132 | |
|
|
133 | if (strstr (RP->layoutstyle, "squarespiral")) |
120 | else if (strstr (RP->layoutstyle, "squarespiral")) |
134 | RP->map_layout_style = LAYOUT_SQUARE_SPIRAL; |
121 | RP->map_layout_style = LAYOUT_SQUARE_SPIRAL; |
135 | |
|
|
136 | /* No style found - choose one randomly */ |
|
|
137 | if (RP->map_layout_style == LAYOUT_NONE) |
122 | else if (RP->map_layout_style == LAYOUT_NONE) |
138 | RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1; |
123 | RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1; /* No style found - choose one randomly */ |
|
|
124 | else |
|
|
125 | abort (); |
139 | |
126 | |
140 | Maze layout = layoutgen (RP); |
127 | Layout layout = layoutgen (RP); |
141 | |
128 | |
142 | #ifdef RMAP_DEBUG |
129 | #ifdef RMAP_DEBUG |
143 | dump_layout (layout, RP); |
130 | dump_layout (layout, RP); |
144 | #endif |
131 | #endif |
145 | |
132 | |
146 | /* increment these for the current map */ |
133 | /* increment these for the current map */ |
147 | RP->dungeon_level += 1; |
134 | RP->dungeon_level += 1; |
148 | /* allow constant-difficulty maps. */ |
135 | /* allow constant-difficulty maps. */ |
149 | /* difficulty+=1; */ |
136 | /* difficulty+=1; */ |
150 | |
137 | |
151 | /* rotate the layout randomly */ |
|
|
152 | rotate_layout (layout, rndm (4)); |
|
|
153 | #ifdef RMAP_DEBUG |
|
|
154 | dump_layout (layout, RP); |
|
|
155 | #endif |
|
|
156 | |
|
|
157 | // need to patch RP becasue following code doesn't use the Maze object |
138 | // need to patch RP becasue following code doesn't use the Layout object |
158 | RP->Xsize = layout->w; |
139 | RP->Xsize = layout->w; |
159 | RP->Ysize = layout->h; |
140 | RP->Ysize = layout->h; |
160 | |
141 | |
161 | /* allocate the map and set the floor */ |
142 | /* allocate the map and set the floor */ |
162 | make_map_floor (layout, RP->floorstyle, RP); |
143 | make_map_floor (layout, RP->floorstyle, RP); |
… | |
… | |
216 | |
197 | |
217 | CEDE; |
198 | CEDE; |
218 | |
199 | |
219 | unblock_exits (this, layout, RP); |
200 | unblock_exits (this, layout, RP); |
220 | |
201 | |
221 | layout.free (); |
|
|
222 | |
|
|
223 | msg = strdup (buf); |
202 | msg = strdup (buf); |
224 | in_memory = MAP_IN_MEMORY; |
203 | in_memory = MAP_IN_MEMORY; |
225 | |
204 | |
226 | CEDE; |
205 | CEDE; |
227 | |
206 | |
228 | return 1; |
207 | return 1; |
229 | } |
208 | } |
230 | |
209 | |
231 | /* function selects the layout function and gives it whatever |
210 | /* function selects the layout function and gives it whatever |
232 | arguments it needs. */ |
211 | arguments it needs. */ |
233 | Maze |
212 | Layout |
234 | layoutgen (random_map_params *RP) |
213 | layoutgen (random_map_params *RP) |
235 | { |
214 | { |
236 | Maze maze (RP); |
215 | Layout layout (RP); |
237 | |
216 | |
238 | switch (RP->map_layout_style) |
217 | switch (RP->map_layout_style) |
239 | { |
218 | { |
240 | case LAYOUT_ONION: |
219 | case LAYOUT_ONION: |
241 | map_gen_onion (maze, RP->layoutoptions1, RP->layoutoptions2); |
220 | map_gen_onion (layout, RP->layoutoptions1, RP->layoutoptions2); |
242 | |
221 | |
243 | if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY)) |
222 | if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY)) |
244 | roomify_layout (maze, RP); |
223 | roomify_layout (layout, RP); |
245 | |
224 | |
246 | break; |
225 | break; |
247 | |
226 | |
248 | case LAYOUT_MAZE: |
227 | case LAYOUT_MAZE: |
249 | maze_gen (maze, rndm (2)); |
228 | maze_gen (layout, rndm (2)); |
250 | |
229 | |
251 | if (!(rndm (2))) |
230 | if (!(rndm (2))) |
252 | doorify_layout (maze, RP); |
231 | doorify_layout (layout, RP); |
253 | |
232 | |
254 | break; |
233 | break; |
255 | |
234 | |
256 | case LAYOUT_SPIRAL: |
235 | case LAYOUT_SPIRAL: |
257 | map_gen_spiral (maze, RP->layoutoptions1); |
236 | map_gen_spiral (layout, RP->layoutoptions1); |
258 | |
237 | |
259 | if (!(rndm (2))) |
238 | if (!(rndm (2))) |
260 | doorify_layout (maze, RP); |
239 | doorify_layout (layout, RP); |
261 | |
240 | |
262 | break; |
241 | break; |
263 | |
242 | |
264 | case LAYOUT_ROGUELIKE: |
243 | case LAYOUT_ROGUELIKE: |
265 | /* Don't put symmetry in rogue maps. There isn't much reason to |
244 | /* Don't put symmetry in rogue maps. There isn't much reason to |
… | |
… | |
268 | * spirals, or maps with lots of passages - making a symmetric rogue |
247 | * spirals, or maps with lots of passages - making a symmetric rogue |
269 | * map fails because its likely that the passages the symmetry process |
248 | * map fails because its likely that the passages the symmetry process |
270 | * creates may not connect the rooms. |
249 | * creates may not connect the rooms. |
271 | */ |
250 | */ |
272 | RP->symmetry_used = SYMMETRY_NONE; |
251 | RP->symmetry_used = SYMMETRY_NONE; |
273 | roguelike_layout_gen (maze, RP->layoutoptions1); |
252 | roguelike_layout_gen (layout, RP->layoutoptions1); |
274 | /* no doorifying... done already */ |
253 | /* no doorifying... done already */ |
275 | break; |
254 | break; |
276 | |
255 | |
277 | case LAYOUT_SNAKE: |
256 | case LAYOUT_SNAKE: |
278 | make_snake_layout (maze, RP->layoutoptions1); |
257 | make_snake_layout (layout, RP->layoutoptions1); |
279 | |
258 | |
280 | if (rndm (2)) |
259 | if (rndm (2)) |
281 | roomify_layout (maze, RP); |
260 | roomify_layout (layout, RP); |
282 | |
261 | |
283 | break; |
262 | break; |
284 | |
263 | |
285 | case LAYOUT_SQUARE_SPIRAL: |
264 | case LAYOUT_SQUARE_SPIRAL: |
286 | make_square_spiral_layout (maze, RP->layoutoptions1); |
265 | make_square_spiral_layout (layout, RP->layoutoptions1); |
287 | |
266 | |
288 | if (rndm (2)) |
267 | if (rndm (2)) |
289 | roomify_layout (maze, RP); |
268 | roomify_layout (layout, RP); |
290 | |
269 | |
291 | break; |
270 | break; |
292 | |
271 | |
293 | default: |
272 | default: |
294 | abort (); |
273 | abort (); |
295 | } |
274 | } |
296 | |
275 | |
|
|
276 | /* rotate the layout randomly */ |
|
|
277 | rotate_layout (layout, rndm (4)); |
|
|
278 | |
297 | symmetrize_layout (maze, RP); |
279 | symmetrize_layout (layout, RP); |
298 | |
280 | |
299 | #ifdef RMAP_DEBUG |
281 | #ifdef RMAP_DEBUG |
300 | dump_layout (maze, RP); |
282 | dump_layout (layout); |
301 | #endif |
283 | #endif |
302 | |
284 | |
303 | if (RP->expand2x) |
285 | if (RP->expand2x) |
304 | expand2x (maze); |
286 | expand2x (layout); |
305 | |
287 | |
306 | return maze; |
288 | return layout; |
307 | } |
289 | } |
308 | |
290 | |
309 | /* takes a map and makes it symmetric: adjusts Xsize and |
291 | /* takes a map and makes it symmetric: adjusts Xsize and |
310 | Ysize to produce a symmetric map. */ |
292 | * Ysize to produce a symmetric map. |
|
|
293 | */ |
311 | static void |
294 | static void |
312 | symmetrize_layout (Maze maze, random_map_params *RP) |
295 | symmetrize_layout (Layout layout, random_map_params *RP) |
313 | { |
296 | { |
314 | if (RP->symmetry_used == SYMMETRY_NONE) |
297 | if (RP->symmetry_used == SYMMETRY_NONE) |
315 | return; |
298 | return; |
316 | |
299 | |
317 | Maze sym_maze ( |
300 | Layout sym_layout ( |
318 | RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY ? maze->w * 2 - 3 : maze->w, |
301 | RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY ? layout->w * 2 - 3 : layout->w, |
319 | RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY ? maze->h * 2 - 3 : maze->h |
302 | RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY ? layout->h * 2 - 3 : layout->h |
320 | ); |
303 | ); |
321 | |
304 | |
322 | if (RP->symmetry_used == SYMMETRY_X) |
305 | if (RP->symmetry_used == SYMMETRY_X) |
323 | for (int i = 0; i < sym_maze->w / 2 + 1; i++) |
306 | for (int i = 0; i < sym_layout->w / 2 + 1; i++) |
324 | for (int j = 0; j < sym_maze->h; j++) |
307 | for (int j = 0; j < sym_layout->h; j++) |
325 | { |
308 | { |
326 | sym_maze[i ][j] = |
309 | sym_layout[i ][j] = |
327 | sym_maze[sym_maze->w - i - 1][j] = maze[i][j]; |
310 | sym_layout[sym_layout->w - i - 1][j] = layout[i][j]; |
328 | } |
311 | } |
329 | |
312 | |
330 | if (RP->symmetry_used == SYMMETRY_Y) |
313 | if (RP->symmetry_used == SYMMETRY_Y) |
331 | for (int i = 0; i < sym_maze->w; i++) |
314 | for (int i = 0; i < sym_layout->w; i++) |
332 | for (int j = 0; j < sym_maze->h / 2 + 1; j++) |
315 | for (int j = 0; j < sym_layout->h / 2 + 1; j++) |
333 | { |
316 | { |
334 | sym_maze[i][j ] = |
317 | sym_layout[i][j ] = |
335 | sym_maze[i][sym_maze->h - j - 1] = maze[i][j]; |
318 | sym_layout[i][sym_layout->h - j - 1] = layout[i][j]; |
336 | } |
319 | } |
337 | |
320 | |
338 | if (RP->symmetry_used == SYMMETRY_XY) |
321 | if (RP->symmetry_used == SYMMETRY_XY) |
339 | for (int i = 0; i < sym_maze->w / 2 + 1; i++) |
322 | for (int i = 0; i < sym_layout->w / 2 + 1; i++) |
340 | for (int j = 0; j < sym_maze->h / 2 + 1; j++) |
323 | for (int j = 0; j < sym_layout->h / 2 + 1; j++) |
341 | { |
324 | { |
342 | sym_maze[i ][j ] = |
325 | sym_layout[i ][j ] = |
343 | sym_maze[i ][sym_maze->h - j - 1] = |
326 | sym_layout[i ][sym_layout->h - j - 1] = |
344 | sym_maze[sym_maze->w - i - 1][j ] = |
327 | sym_layout[sym_layout->w - i - 1][j ] = |
345 | sym_maze[sym_maze->w - i - 1][sym_maze->h - j - 1] = maze[i][j]; |
328 | sym_layout[sym_layout->w - i - 1][sym_layout->h - j - 1] = layout[i][j]; |
346 | } |
329 | } |
347 | |
330 | |
348 | maze.swap (sym_maze); |
331 | layout.swap (sym_layout); |
|
|
332 | sym_layout.free (); |
349 | |
333 | |
350 | /* reconnect disjointed spirals */ |
334 | /* reconnect disjointed spirals */ |
351 | /* reconnect disjointed nethackmazes: the routine for |
335 | /* reconnect disjointed nethacklayouts: the routine for |
352 | spirals will do the trick? */ |
336 | spirals will do the trick? */ |
353 | if (RP->map_layout_style == LAYOUT_SPIRAL |
337 | if (RP->map_layout_style == LAYOUT_SPIRAL |
354 | || RP->map_layout_style == LAYOUT_ROGUELIKE) |
338 | || RP->map_layout_style == LAYOUT_ROGUELIKE) |
355 | connect_spirals (maze->w, maze->h, RP->symmetry_used, maze); |
339 | connect_spirals (layout->w, layout->h, RP->symmetry_used, layout); |
356 | } |
340 | } |
357 | |
341 | |
358 | /* takes a map and rotates it. This completes the |
342 | /* takes a map and rotates it. This completes the |
359 | onion layouts, making them possibly centered on any wall. |
343 | onion layouts, making them possibly centered on any wall. |
360 | It'll modify Xsize and Ysize if they're swapped. |
344 | It'll modify Xsize and Ysize if they're swapped. |
361 | */ |
345 | */ |
362 | static void |
346 | static void |
363 | rotate_layout (Maze maze, int rotation) |
347 | rotate_layout (Layout layout, int rotation) |
364 | { |
348 | { |
|
|
349 | int w = layout->w; |
|
|
350 | int h = layout->h; |
|
|
351 | |
365 | switch (rotation) |
352 | switch (rotation) |
366 | { |
353 | { |
367 | case 2: /* a reflection */ |
354 | case 2: /* a reflection */ |
368 | { |
355 | { |
369 | Maze new_maze (maze->w, maze->h); |
356 | Layout new_layout (w, h); |
370 | |
357 | |
371 | for (int i = 0; i < maze->w; i++) /* copy a reflection back */ |
358 | for (int i = 0; i < w; i++) /* copy a reflection back */ |
372 | for (int j = 0; j < maze->h; j++) |
359 | for (int j = 0; j < h; j++) |
373 | new_maze[i][j] = maze[maze->w - i - 1][maze->h - j - 1]; |
360 | new_layout[i][j] = layout[w - i - 1][h - j - 1]; |
374 | |
361 | |
375 | maze.swap (new_maze); |
362 | layout.swap (new_layout); |
|
|
363 | new_layout.free (); |
376 | } |
364 | } |
|
|
365 | break; |
377 | |
366 | |
378 | case 1: |
367 | case 1: |
379 | case 3: |
368 | case 3: |
380 | { |
369 | { |
381 | Maze new_maze (maze->h, maze->w); |
370 | Layout new_layout (h, w); |
382 | |
371 | |
383 | if (rotation == 1) /* swap x and y */ |
372 | if (rotation == 1) /* swap x and y */ |
384 | for (int i = 0; i < maze->w; i++) |
373 | for (int i = 0; i < w; i++) |
385 | for (int j = 0; j < maze->h; j++) |
374 | for (int j = 0; j < h; j++) |
386 | new_maze[j][i] = maze[i][j]; |
375 | new_layout[j][i] = layout[i][j]; |
387 | |
376 | |
388 | if (rotation == 3) /* swap x and y */ |
377 | if (rotation == 3) /* swap x and y */ |
389 | for (int i = 0; i < maze->w; i++) |
378 | for (int i = 0; i < w; i++) |
390 | for (int j = 0; j < maze->h; j++) |
379 | for (int j = 0; j < h; j++) |
391 | new_maze[j][i] = maze[maze->w - i - 1][maze->h - j - 1]; |
380 | new_layout[j][i] = layout[w - i - 1][h - j - 1]; |
392 | |
381 | |
393 | maze.swap (new_maze); |
382 | layout.swap (new_layout); |
|
|
383 | new_layout.free (); |
394 | } |
384 | } |
|
|
385 | break; |
395 | } |
386 | } |
396 | } |
387 | } |
397 | |
388 | |
398 | /* take a layout and make some rooms in it. |
389 | /* take a layout and make some rooms in it. |
399 | --works best on onions.*/ |
390 | --works best on onions.*/ |
… | |
… | |
968 | walk->copy_to (tmp); |
959 | walk->copy_to (tmp); |
969 | insert_ob_in_ob (tmp, dest_ob); |
960 | insert_ob_in_ob (tmp, dest_ob); |
970 | } |
961 | } |
971 | } |
962 | } |
972 | |
963 | |
|
|
964 | ///////////////////////////////////////////////////////////////////////////// |
|
|
965 | |
973 | MazeData::MazeData (int w, int h) |
966 | LayoutData::LayoutData (int w, int h) |
974 | : w(w), h(h) |
967 | : w(w), h(h) |
975 | { |
968 | { |
976 | int size = (sizeof (char *) + sizeof (char) * h) * w; |
969 | int size = (sizeof (char *) + sizeof (char) * h) * w; |
977 | |
970 | |
978 | col = (char **)salloc<char> (size); |
971 | col = (char **)salloc<char> (size); |
… | |
… | |
981 | |
974 | |
982 | for (int x = w; x--; ) |
975 | for (int x = w; x--; ) |
983 | col [x] = data + x * h; |
976 | col [x] = data + x * h; |
984 | } |
977 | } |
985 | |
978 | |
986 | MazeData::~MazeData () |
979 | LayoutData::~LayoutData () |
987 | { |
980 | { |
988 | int size = (sizeof (char *) + sizeof (char) * h) * w; |
981 | int size = (sizeof (char *) + sizeof (char) * h) * w; |
989 | |
982 | |
990 | sfree ((char *)col, size); |
983 | sfree ((char *)col, size); |
991 | } |
984 | } |
992 | |
985 | |
993 | void MazeData::clear (char fill) |
986 | void LayoutData::clear (char fill) |
994 | { |
987 | { |
995 | memset (col [0], fill, w * h); |
988 | memset (col [0], fill, w * h); |
996 | } |
989 | } |
997 | |
990 | |
998 | void MazeData::border (char fill) |
991 | void LayoutData::border (char fill) |
999 | { |
992 | { |
1000 | for (int i = 0; i < w; i++) col [i][0] = col [i][h - 1] = fill; |
993 | for (int i = 0; i < w; i++) col [i][0] = col [i][h - 1] = fill; |
1001 | for (int j = 0; j < h; j++) col [0][j] = col [w - 1][j] = fill; |
994 | for (int j = 0; j < h; j++) col [0][j] = col [w - 1][j] = fill; |
1002 | } |
995 | } |
1003 | |
996 | |
1004 | |
|
|