… | |
… | |
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); |
|
|
34 | static void rotate_layout (Maze maze, int rotation); |
|
|
35 | |
33 | void |
36 | void |
34 | dump_layout (char **layout, random_map_params *RP) |
37 | dump_layout (char **layout, random_map_params *RP) |
35 | { |
38 | { |
36 | { |
39 | { |
37 | int i, j; |
40 | int i, j; |
… | |
… | |
144 | RP->dungeon_level += 1; |
147 | RP->dungeon_level += 1; |
145 | /* allow constant-difficulty maps. */ |
148 | /* allow constant-difficulty maps. */ |
146 | /* difficulty+=1; */ |
149 | /* difficulty+=1; */ |
147 | |
150 | |
148 | /* rotate the layout randomly */ |
151 | /* rotate the layout randomly */ |
149 | layout = rotate_layout (layout, rndm (4), RP); |
152 | rotate_layout (layout, rndm (4)); |
150 | #ifdef RMAP_DEBUG |
153 | #ifdef RMAP_DEBUG |
151 | dump_layout (layout, RP); |
154 | dump_layout (layout, RP); |
152 | #endif |
155 | #endif |
|
|
156 | |
|
|
157 | // need to patch RP becasue following code doesn't use the Maze object |
|
|
158 | RP->Xsize = layout->w; |
|
|
159 | RP->Ysize = layout->h; |
153 | |
160 | |
154 | /* allocate the map and set the floor */ |
161 | /* allocate the map and set the floor */ |
155 | make_map_floor (layout, RP->floorstyle, RP); |
162 | make_map_floor (layout, RP->floorstyle, RP); |
156 | |
163 | |
157 | /* set region */ |
164 | /* set region */ |
… | |
… | |
224 | /* function selects the layout function and gives it whatever |
231 | /* function selects the layout function and gives it whatever |
225 | arguments it needs. */ |
232 | arguments it needs. */ |
226 | Maze |
233 | Maze |
227 | layoutgen (random_map_params *RP) |
234 | layoutgen (random_map_params *RP) |
228 | { |
235 | { |
229 | Maze maze; |
236 | Maze maze (RP); |
230 | |
|
|
231 | int oxsize = RP->Xsize, oysize = RP->Ysize; |
|
|
232 | |
237 | |
233 | switch (RP->map_layout_style) |
238 | switch (RP->map_layout_style) |
234 | { |
239 | { |
235 | case LAYOUT_ONION: |
240 | case LAYOUT_ONION: |
236 | maze = map_gen_onion (RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2); |
241 | map_gen_onion (maze, RP->layoutoptions1, RP->layoutoptions2); |
237 | |
242 | |
238 | if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY)) |
243 | if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY)) |
239 | roomify_layout (maze, RP); |
244 | roomify_layout (maze, RP); |
240 | |
245 | |
241 | break; |
246 | break; |
242 | |
247 | |
243 | case LAYOUT_MAZE: |
248 | case LAYOUT_MAZE: |
244 | maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2)); |
249 | maze_gen (maze, rndm (2)); |
245 | |
250 | |
246 | if (!(rndm (2))) |
251 | if (!(rndm (2))) |
247 | doorify_layout (maze, RP); |
252 | doorify_layout (maze, RP); |
248 | |
253 | |
249 | break; |
254 | break; |
250 | |
255 | |
251 | case LAYOUT_SPIRAL: |
256 | case LAYOUT_SPIRAL: |
252 | maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1); |
257 | map_gen_spiral (maze, RP->layoutoptions1); |
253 | |
258 | |
254 | if (!(rndm (2))) |
259 | if (!(rndm (2))) |
255 | doorify_layout (maze, RP); |
260 | doorify_layout (maze, RP); |
256 | |
261 | |
257 | break; |
262 | break; |
… | |
… | |
263 | * spirals, or maps with lots of passages - making a symmetric rogue |
268 | * spirals, or maps with lots of passages - making a symmetric rogue |
264 | * map fails because its likely that the passages the symmetry process |
269 | * map fails because its likely that the passages the symmetry process |
265 | * creates may not connect the rooms. |
270 | * creates may not connect the rooms. |
266 | */ |
271 | */ |
267 | RP->symmetry_used = SYMMETRY_NONE; |
272 | RP->symmetry_used = SYMMETRY_NONE; |
268 | RP->Ysize = oysize; |
|
|
269 | RP->Xsize = oxsize; |
|
|
270 | maze = roguelike_layout_gen (RP->Xsize, RP->Ysize, RP->layoutoptions1); |
273 | roguelike_layout_gen (maze, RP->layoutoptions1); |
271 | /* no doorifying... done already */ |
274 | /* no doorifying... done already */ |
272 | break; |
275 | break; |
273 | |
276 | |
274 | case LAYOUT_SNAKE: |
277 | case LAYOUT_SNAKE: |
275 | maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1); |
278 | make_snake_layout (maze, RP->layoutoptions1); |
276 | |
279 | |
277 | if (rndm (2)) |
280 | if (rndm (2)) |
278 | roomify_layout (maze, RP); |
281 | roomify_layout (maze, RP); |
279 | |
282 | |
280 | break; |
283 | break; |
281 | |
284 | |
282 | case LAYOUT_SQUARE_SPIRAL: |
285 | case LAYOUT_SQUARE_SPIRAL: |
283 | maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1); |
286 | make_square_spiral_layout (maze, RP->layoutoptions1); |
284 | |
287 | |
285 | if (rndm (2)) |
288 | if (rndm (2)) |
286 | roomify_layout (maze, RP); |
289 | roomify_layout (maze, RP); |
287 | |
290 | |
288 | break; |
291 | break; |
289 | |
292 | |
290 | default: |
293 | default: |
291 | abort (); |
294 | abort (); |
292 | } |
295 | } |
293 | |
296 | |
294 | maze = symmetrize_layout (maze, RP->symmetry_used, RP); |
297 | symmetrize_layout (maze, RP); |
295 | |
298 | |
296 | #ifdef RMAP_DEBUG |
299 | #ifdef RMAP_DEBUG |
297 | dump_layout (maze, RP); |
300 | dump_layout (maze, RP); |
298 | #endif |
301 | #endif |
299 | |
302 | |
300 | if (RP->expand2x) |
303 | if (RP->expand2x) |
301 | { |
304 | expand2x (maze); |
302 | maze = expand2x (maze, RP->Xsize, RP->Ysize); |
|
|
303 | RP->Xsize = RP->Xsize * 2 - 1; |
|
|
304 | RP->Ysize = RP->Ysize * 2 - 1; |
|
|
305 | } |
|
|
306 | |
305 | |
307 | return maze; |
306 | return maze; |
308 | } |
307 | } |
309 | |
308 | |
310 | /* takes a map and makes it symmetric: adjusts Xsize and |
309 | /* takes a map and makes it symmetric: adjusts Xsize and |
311 | Ysize to produce a symmetric map. */ |
310 | Ysize to produce a symmetric map. */ |
312 | Maze |
311 | static void |
313 | symmetrize_layout (Maze maze, int sym, random_map_params *RP) |
312 | symmetrize_layout (Maze maze, random_map_params *RP) |
314 | { |
313 | { |
315 | int i, j; |
|
|
316 | int Xsize_orig, Ysize_orig; |
|
|
317 | |
|
|
318 | Xsize_orig = RP->Xsize; |
|
|
319 | Ysize_orig = RP->Ysize; |
|
|
320 | |
|
|
321 | RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used. */ |
|
|
322 | |
|
|
323 | if (sym == SYMMETRY_NONE) |
314 | if (RP->symmetry_used == SYMMETRY_NONE) |
324 | { |
|
|
325 | RP->Xsize = Xsize_orig; |
|
|
326 | RP->Ysize = Ysize_orig; |
|
|
327 | |
|
|
328 | return maze; |
315 | return; |
329 | } |
|
|
330 | |
316 | |
331 | /* pick new sizes */ |
|
|
332 | RP->Xsize = ((sym == SYMMETRY_X || sym == SYMMETRY_XY) ? RP->Xsize * 2 - 3 : RP->Xsize); |
|
|
333 | RP->Ysize = ((sym == SYMMETRY_Y || sym == SYMMETRY_XY) ? RP->Ysize * 2 - 3 : RP->Ysize); |
|
|
334 | |
|
|
335 | Maze sym_maze (RP); |
317 | Maze sym_maze ( |
|
|
318 | RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY ? maze->w * 2 - 3 : maze->w, |
|
|
319 | RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY ? maze->h * 2 - 3 : maze->h |
|
|
320 | ); |
336 | |
321 | |
337 | if (sym == SYMMETRY_X) |
322 | if (RP->symmetry_used == SYMMETRY_X) |
338 | for (i = 0; i < RP->Xsize / 2 + 1; i++) |
323 | for (int i = 0; i < sym_maze->w / 2 + 1; i++) |
339 | for (j = 0; j < RP->Ysize; j++) |
324 | for (int j = 0; j < sym_maze->h; j++) |
340 | { |
|
|
341 | sym_maze[i][j] = maze[i][j]; |
|
|
342 | sym_maze[RP->Xsize - i - 1][j] = maze[i][j]; |
|
|
343 | } |
325 | { |
344 | |
326 | sym_maze[i ][j] = |
345 | if (sym == SYMMETRY_Y) |
327 | sym_maze[sym_maze->w - i - 1][j] = maze[i][j]; |
346 | for (i = 0; i < RP->Xsize; i++) |
|
|
347 | for (j = 0; j < RP->Ysize / 2 + 1; j++) |
|
|
348 | { |
328 | } |
349 | sym_maze[i][j] = maze[i][j]; |
329 | |
350 | sym_maze[i][RP->Ysize - j - 1] = maze[i][j]; |
330 | if (RP->symmetry_used == SYMMETRY_Y) |
|
|
331 | for (int i = 0; i < sym_maze->w; i++) |
|
|
332 | for (int j = 0; j < sym_maze->h / 2 + 1; j++) |
351 | } |
333 | { |
352 | |
334 | sym_maze[i][j ] = |
353 | if (sym == SYMMETRY_XY) |
335 | sym_maze[i][sym_maze->h - j - 1] = maze[i][j]; |
354 | for (i = 0; i < RP->Xsize / 2 + 1; i++) |
|
|
355 | for (j = 0; j < RP->Ysize / 2 + 1; j++) |
|
|
356 | { |
336 | } |
357 | sym_maze[i][j] = maze[i][j]; |
337 | |
358 | sym_maze[i][RP->Ysize - j - 1] = maze[i][j]; |
338 | if (RP->symmetry_used == SYMMETRY_XY) |
359 | sym_maze[RP->Xsize - i - 1][j] = maze[i][j]; |
339 | for (int i = 0; i < sym_maze->w / 2 + 1; i++) |
360 | sym_maze[RP->Xsize - i - 1][RP->Ysize - j - 1] = maze[i][j]; |
340 | for (int j = 0; j < sym_maze->h / 2 + 1; j++) |
361 | } |
341 | { |
|
|
342 | sym_maze[i ][j ] = |
|
|
343 | sym_maze[i ][sym_maze->h - j - 1] = |
|
|
344 | sym_maze[sym_maze->w - i - 1][j ] = |
|
|
345 | sym_maze[sym_maze->w - i - 1][sym_maze->h - j - 1] = maze[i][j]; |
|
|
346 | } |
362 | |
347 | |
363 | maze.free (); |
348 | maze.swap (sym_maze); |
364 | |
349 | |
365 | /* reconnect disjointed spirals */ |
350 | /* reconnect disjointed spirals */ |
366 | if (RP->map_layout_style == LAYOUT_SPIRAL) |
|
|
367 | connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze); |
|
|
368 | |
|
|
369 | /* reconnect disjointed nethackmazes: the routine for |
351 | /* reconnect disjointed nethackmazes: the routine for |
370 | spirals will do the trick? */ |
352 | spirals will do the trick? */ |
|
|
353 | if (RP->map_layout_style == LAYOUT_SPIRAL |
371 | if (RP->map_layout_style == LAYOUT_ROGUELIKE) |
354 | || RP->map_layout_style == LAYOUT_ROGUELIKE) |
372 | connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze); |
355 | connect_spirals (maze->w, maze->h, RP->symmetry_used, maze); |
373 | |
|
|
374 | return sym_maze; |
|
|
375 | } |
356 | } |
376 | |
357 | |
377 | /* takes a map and rotates it. This completes the |
358 | /* takes a map and rotates it. This completes the |
378 | onion layouts, making them possibly centered on any wall. |
359 | onion layouts, making them possibly centered on any wall. |
379 | It'll modify Xsize and Ysize if they're swapped. |
360 | It'll modify Xsize and Ysize if they're swapped. |
380 | */ |
361 | */ |
381 | Maze |
362 | static void |
382 | rotate_layout (Maze maze, int rotation, random_map_params *RP) |
363 | rotate_layout (Maze maze, int rotation) |
383 | { |
364 | { |
384 | switch (rotation) |
365 | switch (rotation) |
385 | { |
366 | { |
386 | case 2: /* a reflection */ |
367 | case 2: /* a reflection */ |
387 | { |
368 | { |
388 | Maze new_maze (RP); |
369 | Maze new_maze (maze->w, maze->h); |
389 | |
370 | |
390 | for (int i = 0; i < RP->Xsize; i++) /* copy a reflection back */ |
371 | for (int i = 0; i < maze->w; i++) /* copy a reflection back */ |
391 | for (int j = 0; j < RP->Ysize; j++) |
372 | for (int j = 0; j < maze->h; j++) |
392 | new_maze[i][j] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1]; |
373 | new_maze[i][j] = maze[maze->w - i - 1][maze->h - j - 1]; |
393 | |
374 | |
394 | maze.free (); |
|
|
395 | maze = new_maze; |
375 | maze.swap (new_maze); |
396 | } |
376 | } |
397 | |
377 | |
398 | case 1: |
378 | case 1: |
399 | case 3: |
379 | case 3: |
400 | { |
380 | { |
401 | Maze new_maze (RP->Ysize, RP->Xsize); |
381 | Maze new_maze (maze->h, maze->w); |
402 | |
382 | |
403 | if (rotation == 1) /* swap x and y */ |
383 | if (rotation == 1) /* swap x and y */ |
404 | for (int i = 0; i < RP->Xsize; i++) |
384 | for (int i = 0; i < maze->w; i++) |
405 | for (int j = 0; j < RP->Ysize; j++) |
385 | for (int j = 0; j < maze->h; j++) |
406 | new_maze[j][i] = maze[i][j]; |
386 | new_maze[j][i] = maze[i][j]; |
407 | |
387 | |
408 | if (rotation == 3) /* swap x and y */ |
388 | if (rotation == 3) /* swap x and y */ |
409 | for (int i = 0; i < RP->Xsize; i++) |
389 | for (int i = 0; i < maze->w; i++) |
410 | for (int j = 0; j < RP->Ysize; j++) |
390 | for (int j = 0; j < maze->h; j++) |
411 | new_maze[j][i] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1]; |
391 | new_maze[j][i] = maze[maze->w - i - 1][maze->h - j - 1]; |
412 | |
392 | |
413 | maze.free (); |
|
|
414 | maze = new_maze; |
393 | maze.swap (new_maze); |
415 | swap (RP->Xsize, RP->Ysize); |
|
|
416 | } |
394 | } |
417 | } |
395 | } |
418 | |
|
|
419 | return maze; |
|
|
420 | } |
396 | } |
421 | |
397 | |
422 | /* take a layout and make some rooms in it. |
398 | /* take a layout and make some rooms in it. |
423 | --works best on onions.*/ |
399 | --works best on onions.*/ |
424 | void |
400 | void |
… | |
… | |
992 | walk->copy_to (tmp); |
968 | walk->copy_to (tmp); |
993 | insert_ob_in_ob (tmp, dest_ob); |
969 | insert_ob_in_ob (tmp, dest_ob); |
994 | } |
970 | } |
995 | } |
971 | } |
996 | |
972 | |
997 | MazeData::MazeData (int xsize, int ysize) |
973 | MazeData::MazeData (int w, int h) |
|
|
974 | : w(w), h(h) |
998 | { |
975 | { |
999 | int size = xsize * ysize |
976 | int size = (sizeof (char *) + sizeof (char) * h) * w; |
1000 | + sizeof (char *) * xsize |
|
|
1001 | + sizeof (char *); |
|
|
1002 | |
977 | |
1003 | col = (char **)salloc0<char> (size); |
978 | col = (char **)salloc<char> (size); |
1004 | *col++ = (char *)size; |
|
|
1005 | |
979 | |
1006 | char *data = (char *)(col + xsize); |
980 | char *data = (char *)(col + w); |
1007 | |
981 | |
1008 | for (int x = xsize; x--; ) |
982 | for (int x = w; x--; ) |
1009 | col [x] = data + x * ysize; |
983 | col [x] = data + x * h; |
1010 | } |
984 | } |
1011 | |
985 | |
1012 | MazeData::~MazeData () |
986 | MazeData::~MazeData () |
1013 | { |
987 | { |
1014 | int size = (long)*--col; |
988 | int size = (sizeof (char *) + sizeof (char) * h) * w; |
|
|
989 | |
1015 | sfree ((char *)col, size); |
990 | sfree ((char *)col, size); |
1016 | } |
991 | } |
1017 | |
992 | |
|
|
993 | void MazeData::clear (char fill) |
|
|
994 | { |
|
|
995 | memset (col [0], fill, w * h); |
|
|
996 | } |
|
|
997 | |
|
|
998 | void MazeData::border (char fill) |
|
|
999 | { |
|
|
1000 | 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; |
|
|
1002 | } |
|
|
1003 | |
|
|
1004 | |