--- deliantra/server/random_maps/room_gen_onion.C 2007/11/08 19:43:25 1.12 +++ deliantra/server/random_maps/room_gen_onion.C 2010/03/26 01:04:44 1.22 @@ -1,22 +1,23 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team - * Copyright (©) 1992,2007 Frank Tore Johansen + * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2001 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992 Frank Tore Johansen * - * Deliantra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Deliantra is free software: you can redistribute it and/or modify it under + * the terms of the Affero GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the Affero GNU General Public License + * and the GNU General Public License along with this program. If not, see + * . * * The authors can be reached via e-mail to */ @@ -51,35 +52,29 @@ #include #include +#include -#ifndef MIN -# define MIN(x,y) (((x)<(y))? (x):(y)) -#endif -void centered_onion (char **maze, int xsize, int ysize, int option, int layers); -void bottom_centered_onion (char **maze, int xsize, int ysize, int option, int layers); -void bottom_right_centered_onion (char **maze, int xsize, int ysize, int option, int layers); +static void centered_onion (char **maze, int xsize, int ysize, int option, int layers); +static void bottom_centered_onion (char **maze, int xsize, int ysize, int option, int layers); +static void bottom_right_centered_onion (char **maze, int xsize, int ysize, int option, int layers); +static void draw_onion (char **maze, float *xlocations, float *ylocations, int layers); +static void make_doors (char **maze, float *xlocations, float *ylocations, int layers, int options); -void draw_onion (char **maze, float *xlocations, float *ylocations, int layers); -void make_doors (char **maze, float *xlocations, float *ylocations, int layers, int options); - -char ** -map_gen_onion (int xsize, int ysize, int option, int layers) +void +map_gen_onion (Layout maze, int option, int layers) { int i, j; - /* allocate that array, set it up */ - char **maze = (char **) calloc (sizeof (char *), xsize); + int xsize = maze->w; + int ysize = maze->h; - for (i = 0; i < xsize; i++) - { - maze[i] = (char *) calloc (sizeof (char), ysize); - } + maze->clear (); /* pick some random options if option = 0 */ if (option == 0) { - switch (rndm (3)) + switch (rmg_rndm (3)) { case 0: option |= RMOPT_CENTERED; @@ -91,23 +86,17 @@ option |= RMOPT_BOTTOM_R; break; } - if (rndm (2)) - option |= RMOPT_LINEAR; - if (rndm (2)) - option |= RMOPT_IRR_SPACE; + + if (rmg_rndm (2)) option |= RMOPT_LINEAR; + if (rmg_rndm (2)) option |= RMOPT_IRR_SPACE; } /* write the outer walls, if appropriate. */ if (!(option & RMOPT_WALL_OFF)) - { - for (i = 0; i < xsize; i++) - maze[i][0] = maze[i][ysize - 1] = '#'; - for (j = 0; j < ysize; j++) - maze[0][j] = maze[xsize - 1][j] = '#'; - }; + maze->border (); if (option & RMOPT_WALLS_ONLY) - return maze; + return; /* pick off the mutually exclusive options */ if (option & RMOPT_BOTTOM_R) @@ -116,18 +105,15 @@ bottom_centered_onion (maze, xsize, ysize, option, layers); else if (option & RMOPT_CENTERED) centered_onion (maze, xsize, ysize, option, layers); - - return maze; } -void +static void centered_onion (char **maze, int xsize, int ysize, int option, int layers) { int i, maxlayers; - float *xlocations; - float *ylocations; - maxlayers = (MIN (xsize, ysize) - 2) / 5; + maxlayers = (min (xsize, ysize) - 2) / 5; + if (!maxlayers) return; /* map too small to onionize */ @@ -135,10 +121,10 @@ layers = maxlayers; if (layers == 0) - layers = rndm (maxlayers) + 1; + layers = rmg_rndm (maxlayers) + 1; - xlocations = (float *) calloc (sizeof (float), 2 * layers); - ylocations = (float *) calloc (sizeof (float), 2 * layers); + float *xlocations = salloc0 (2 * layers); + float *ylocations = salloc0 (2 * layers); /* place all the walls */ if (option & RMOPT_IRR_SPACE) /* randomly spaced */ @@ -149,17 +135,16 @@ x_spaces_available = (xsize - 2) - 6 * layers + 1; y_spaces_available = (ysize - 2) - 6 * layers + 1; - /* pick an initial random pitch */ for (i = 0; i < 2 * layers; i++) { float xpitch = 2, ypitch = 2; if (x_spaces_available > 0) - xpitch = 2 + (rndm (x_spaces_available) + rndm (x_spaces_available) + rndm (x_spaces_available)) / 3; + xpitch = 2 + (rmg_rndm (x_spaces_available) + rmg_rndm (x_spaces_available) + rmg_rndm (x_spaces_available)) / 3; if (y_spaces_available > 0) - ypitch = 2 + (rndm (y_spaces_available) + rndm (y_spaces_available) + rndm (y_spaces_available)) / 3; + ypitch = 2 + (rmg_rndm (y_spaces_available) + rmg_rndm (y_spaces_available) + rmg_rndm (y_spaces_available)) / 3; xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch; ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch; @@ -168,14 +153,17 @@ } } + if (!(option & RMOPT_IRR_SPACE)) { /* evenly spaced */ float xpitch, ypitch; /* pitch of the onion layers */ xpitch = (xsize - 2.0) / (2.0 * layers + 1); ypitch = (ysize - 2.0) / (2.0 * layers + 1); + xlocations[0] = xpitch; ylocations[0] = ypitch; + for (i = 1; i < 2 * layers; i++) { xlocations[i] = xlocations[i - 1] + xpitch; @@ -184,29 +172,31 @@ } /* draw all the onion boxes. */ - draw_onion (maze, xlocations, ylocations, layers); make_doors (maze, xlocations, ylocations, layers, option); + sfree (xlocations, 2 * layers); + sfree (ylocations, 2 * layers); } -void +static void bottom_centered_onion (char **maze, int xsize, int ysize, int option, int layers) { int i, maxlayers; - float *xlocations; - float *ylocations; - maxlayers = (MIN (xsize, ysize) - 2) / 5; + maxlayers = (min (xsize, ysize) - 2) / 5; + if (!maxlayers) return; /* map too small to onionize */ + if (layers > maxlayers) layers = maxlayers; + if (layers == 0) - layers = rndm (maxlayers) + 1; - xlocations = (float *) calloc (sizeof (float), 2 * layers); - ylocations = (float *) calloc (sizeof (float), 2 * layers); + layers = rmg_rndm (maxlayers) + 1; + float *xlocations = salloc0 (2 * layers); + float *ylocations = salloc0 (2 * layers); /* place all the walls */ if (option & RMOPT_IRR_SPACE) /* randomly spaced */ @@ -217,19 +207,19 @@ x_spaces_available = (xsize - 2) - 6 * layers + 1; y_spaces_available = (ysize - 2) - 3 * layers + 1; - /* pick an initial random pitch */ for (i = 0; i < 2 * layers; i++) { float xpitch = 2, ypitch = 2; if (x_spaces_available > 0) - xpitch = 2 + (rndm (x_spaces_available) + rndm (x_spaces_available) + rndm (x_spaces_available)) / 3; + xpitch = 2 + (rmg_rndm (x_spaces_available) + rmg_rndm (x_spaces_available) + rmg_rndm (x_spaces_available)) / 3; if (y_spaces_available > 0) - ypitch = 2 + (rndm (y_spaces_available) + rndm (y_spaces_available) + rndm (y_spaces_available)) / 3; + ypitch = 2 + (rmg_rndm (y_spaces_available) + rmg_rndm (y_spaces_available) + rmg_rndm (y_spaces_available)) / 3; xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch; + if (i < layers) ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch; else @@ -238,19 +228,22 @@ x_spaces_available -= (int) (xpitch - 2); y_spaces_available -= (int) (ypitch - 2); } - } + if (!(option & RMOPT_IRR_SPACE)) { /* evenly spaced */ float xpitch, ypitch; /* pitch of the onion layers */ xpitch = (xsize - 2.0) / (2.0 * layers + 1); ypitch = (ysize - 2.0) / (layers + 1); + xlocations[0] = xpitch; ylocations[0] = ypitch; + for (i = 1; i < 2 * layers; i++) { xlocations[i] = xlocations[i - 1] + xpitch; + if (i < layers) ylocations[i] = ylocations[i - 1] + ypitch; else @@ -263,12 +256,12 @@ draw_onion (maze, xlocations, ylocations, layers); make_doors (maze, xlocations, ylocations, layers, option); + sfree (xlocations, 2 * layers); + sfree (ylocations, 2 * layers); } - -/* draw_boxes: draws the lines in the maze defining the onion layers */ - -void +/* draw_boxes: draws the lines in the maze defining the onion layers */ +static void draw_onion (char **maze, float *xlocations, float *ylocations, int layers) { int i, j, l; @@ -298,7 +291,7 @@ } } -void +static void make_doors (char **maze, float *xlocations, float *ylocations, int layers, int options) { int freedoms; /* number of different walls on which we could place a door */ @@ -306,15 +299,18 @@ int l, x1 = 0, x2, y1 = 0, y2; freedoms = 4; /* centered */ + if (options & RMOPT_BOTTOM_C) freedoms = 3; + if (options & RMOPT_BOTTOM_R) freedoms = 2; + if (layers <= 0) return; /* pick which wall will have a door. */ - which_wall = rndm (freedoms) + 1; + which_wall = rmg_rndm (freedoms) + 1; for (l = 0; l < layers; l++) { if (options & RMOPT_LINEAR) @@ -349,7 +345,7 @@ } else { /* random door placement. */ - which_wall = rndm (freedoms) + 1; + which_wall = rmg_rndm (freedoms) + 1; switch (which_wall) { case 1: @@ -357,7 +353,7 @@ x1 = (int) xlocations[l]; y2 = (int) (ylocations[2 * layers - l - 1] - ylocations[l] - 1); if (y2 > 0) - y1 = (int) (ylocations[l] + rndm (y2) + 1); + y1 = (int) (ylocations[l] + rmg_rndm (y2) + 1); else y1 = (int) (ylocations[l] + 1); break; @@ -366,7 +362,7 @@ { /* top wall placement */ x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; if (x2 > 0) - x1 = (int) (xlocations[l] + rndm (x2) + 1); + x1 = (int) (xlocations[l] + rmg_rndm (x2) + 1); else x1 = (int) (xlocations[l] + 1); y1 = (int) ylocations[l]; @@ -377,7 +373,7 @@ x1 = (int) xlocations[2 * layers - l - 1]; y2 = (int) ((-ylocations[l] + ylocations[2 * layers - l - 1])) - 1; if (y2 > 0) - y1 = (int) (ylocations[l] + rndm (y2) + 1); + y1 = (int) (ylocations[l] + rmg_rndm (y2) + 1); else y1 = (int) (ylocations[l] + 1); @@ -387,7 +383,7 @@ { /* bottom wall placement */ x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; if (x2 > 0) - x1 = (int) (xlocations[l] + rndm (x2) + 1); + x1 = (int) (xlocations[l] + rmg_rndm (x2) + 1); else x1 = (int) (xlocations[l] + 1); y1 = (int) ylocations[2 * layers - l - 1]; @@ -396,6 +392,7 @@ } } + if (options & RMOPT_NO_DOORS) maze[x1][y1] = '#'; /* no door. */ else @@ -406,31 +403,28 @@ l = layers - 1; x1 = (int) (xlocations[l] + xlocations[2 * layers - l - 1]) / 2; y1 = (int) (ylocations[l] + ylocations[2 * layers - l - 1]) / 2; - maze[x1][y1] = 'C'; - - /* not needed anymore */ - free (xlocations); - free (ylocations); + maze[x1][y1] = 'C'; } -void +static void bottom_right_centered_onion (char **maze, int xsize, int ysize, int option, int layers) { int i, maxlayers; - float *xlocations; - float *ylocations; - maxlayers = (MIN (xsize, ysize) - 2) / 5; + maxlayers = (min (xsize, ysize) - 2) / 5; + if (!maxlayers) return; /* map too small to onionize */ + if (layers > maxlayers) layers = maxlayers; + if (layers == 0) - layers = rndm (maxlayers) + 1; + layers = rmg_rndm (maxlayers) + 1; - xlocations = (float *) calloc (sizeof (float), 2 * layers); - ylocations = (float *) calloc (sizeof (float), 2 * layers); + float *xlocations = salloc0 (2 * layers); + float *ylocations = salloc0 (2 * layers); /* place all the walls */ if (option & RMOPT_IRR_SPACE) /* randomly spaced */ @@ -448,10 +442,10 @@ float xpitch = 2, ypitch = 2; if (x_spaces_available > 0) - xpitch = 2 + (rndm (x_spaces_available) + rndm (x_spaces_available) + rndm (x_spaces_available)) / 3; + xpitch = 2 + (rmg_rndm (x_spaces_available) + rmg_rndm (x_spaces_available) + rmg_rndm (x_spaces_available)) / 3; if (y_spaces_available > 0) - ypitch = 2 + (rndm (y_spaces_available) + rndm (y_spaces_available) + rndm (y_spaces_available)) / 3; + ypitch = 2 + (rmg_rndm (y_spaces_available) + rmg_rndm (y_spaces_available) + rmg_rndm (y_spaces_available)) / 3; if (i < layers) xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch; @@ -462,25 +456,29 @@ ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch; else ylocations[i] = ysize - 1; + x_spaces_available -= (int) (xpitch - 2); y_spaces_available -= (int) (ypitch - 2); } - } + if (!(option & RMOPT_IRR_SPACE)) { /* evenly spaced */ float xpitch, ypitch; /* pitch of the onion layers */ xpitch = (xsize - 2.0) / (2.0 * layers + 1); ypitch = (ysize - 2.0) / (layers + 1); + xlocations[0] = xpitch; ylocations[0] = ypitch; + for (i = 1; i < 2 * layers; i++) { if (i < layers) xlocations[i] = xlocations[i - 1] + xpitch; else xlocations[i] = xsize - 1; + if (i < layers) ylocations[i] = ylocations[i - 1] + ypitch; else @@ -493,4 +491,7 @@ draw_onion (maze, xlocations, ylocations, layers); make_doors (maze, xlocations, ylocations, layers, option); + sfree (xlocations, 2 * layers); + sfree (ylocations, 2 * layers); } +