--- deliantra/server/random_maps/room_gen_onion.C 2006/09/10 16:06:37 1.3 +++ deliantra/server/random_maps/room_gen_onion.C 2011/04/23 04:56:53 1.26 @@ -1,33 +1,27 @@ - /* - * static char *room_gen_onion_c = - * "$Id: room_gen_onion.C,v 1.3 2006/09/10 16:06:37 root Exp $"; + * This file is part of Deliantra, the Roguelike Realtime MMORPG. + * + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 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 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 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 */ -/* - CrossFire, A Multiplayer game for X-windows - - Copyright (C) 2001 Mark Wedel & Crossfire Development Team - Copyright (C) 1992 Frank Tore Johansen - - This program 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - The authors can be reached via e-mail at crossfire-devel@real-time.com -*/ - - /* The onion room generator: Onion rooms are like this: @@ -57,96 +51,83 @@ #include -#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 (RANDOM () % 3) + switch (rmg_rndm (3)) { - case 0: - option |= OPT_CENTERED; - break; - case 1: - option |= OPT_BOTTOM_C; - break; - case 2: - option |= OPT_BOTTOM_R; - break; - } - if (RANDOM () % 2) - option |= OPT_LINEAR; - if (RANDOM () % 2) - option |= OPT_IRR_SPACE; + case 0: + option |= RMOPT_CENTERED; + break; + case 1: + option |= RMOPT_BOTTOM_C; + break; + case 2: + option |= RMOPT_BOTTOM_R; + break; + } + + if (rmg_rndm (2)) option |= RMOPT_LINEAR; + if (rmg_rndm (2)) option |= RMOPT_IRR_SPACE; } /* write the outer walls, if appropriate. */ - if (!(option & OPT_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] = '#'; - }; + if (!(option & RMOPT_WALL_OFF)) + maze.border (); - if (option & OPT_WALLS_ONLY) - return maze; + if (option & RMOPT_WALLS_ONLY) + return; /* pick off the mutually exclusive options */ - if (option & OPT_BOTTOM_R) + if (option & RMOPT_BOTTOM_R) bottom_right_centered_onion (maze, xsize, ysize, option, layers); - else if (option & OPT_BOTTOM_C) + else if (option & RMOPT_BOTTOM_C) bottom_centered_onion (maze, xsize, ysize, option, layers); - else if (option & OPT_CENTERED) + 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 */ + if (layers > maxlayers) layers = maxlayers; + if (layers == 0) - layers = (RANDOM () % 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 & OPT_IRR_SPACE) /* randomly spaced */ + if (option & RMOPT_IRR_SPACE) /* randomly spaced */ { int x_spaces_available, y_spaces_available; @@ -154,17 +135,17 @@ 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 + (RANDOM () % x_spaces_available + RANDOM () % x_spaces_available + RANDOM () % 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 + (RANDOM () % y_spaces_available + RANDOM () % y_spaces_available + RANDOM () % 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; x_spaces_available -= (int) (xpitch - 2); @@ -172,14 +153,17 @@ } } - if (!(option & OPT_IRR_SPACE)) + + 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; @@ -188,32 +172,34 @@ } /* 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 = (RANDOM () % 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 & OPT_IRR_SPACE) /* randomly spaced */ + if (option & RMOPT_IRR_SPACE) /* randomly spaced */ { int x_spaces_available, y_spaces_available; @@ -221,38 +207,43 @@ 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 + (RANDOM () % x_spaces_available + RANDOM () % x_spaces_available + RANDOM () % 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 + (RANDOM () % y_spaces_available + RANDOM () % y_spaces_available + RANDOM () % 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 ylocations[i] = ysize - 1; + x_spaces_available -= (int) (xpitch - 2); y_spaces_available -= (int) (ypitch - 2); } - } - if (!(option & OPT_IRR_SPACE)) + + 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 @@ -265,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; @@ -300,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 */ @@ -308,96 +299,101 @@ int l, x1 = 0, x2, y1 = 0, y2; freedoms = 4; /* centered */ - if (options & OPT_BOTTOM_C) + + if (options & RMOPT_BOTTOM_C) freedoms = 3; - if (options & OPT_BOTTOM_R) + + if (options & RMOPT_BOTTOM_R) freedoms = 2; + if (layers <= 0) return; + /* pick which wall will have a door. */ - which_wall = RANDOM () % freedoms + 1; + which_wall = rmg_rndm (freedoms) + 1; for (l = 0; l < layers; l++) { - if (options & OPT_LINEAR) + if (options & RMOPT_LINEAR) { /* linear door placement. */ switch (which_wall) { - case 1: - { /* left hand wall */ - x1 = (int) xlocations[l]; - y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2); - break; - } - case 2: - { /* top wall placement */ - x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2); - y1 = (int) ylocations[l]; - break; - } - case 3: - { /* right wall placement */ - x1 = (int) xlocations[2 * layers - l - 1]; - y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2); - break; - } - case 4: - { /* bottom wall placement */ - x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2); - y1 = (int) ylocations[2 * layers - l - 1]; - break; - } + case 1: + { /* left hand wall */ + x1 = (int) xlocations[l]; + y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2); + break; + } + case 2: + { /* top wall placement */ + x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2); + y1 = (int) ylocations[l]; + break; + } + case 3: + { /* right wall placement */ + x1 = (int) xlocations[2 * layers - l - 1]; + y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2); + break; + } + case 4: + { /* bottom wall placement */ + x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2); + y1 = (int) ylocations[2 * layers - l - 1]; + break; + } } } else { /* random door placement. */ - which_wall = RANDOM () % freedoms + 1; + which_wall = rmg_rndm (freedoms) + 1; switch (which_wall) { - case 1: - { /* left hand wall */ - x1 = (int) xlocations[l]; - y2 = (int) (ylocations[2 * layers - l - 1] - ylocations[l] - 1); - if (y2 > 0) - y1 = (int) (ylocations[l] + RANDOM () % y2 + 1); - else - y1 = (int) (ylocations[l] + 1); - break; - } - case 2: - { /* top wall placement */ - x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; - if (x2 > 0) - x1 = (int) (xlocations[l] + RANDOM () % x2 + 1); - else - x1 = (int) (xlocations[l] + 1); - y1 = (int) ylocations[l]; - break; - } - case 3: - { /* right wall placement */ - x1 = (int) xlocations[2 * layers - l - 1]; - y2 = (int) ((-ylocations[l] + ylocations[2 * layers - l - 1])) - 1; - if (y2 > 0) - y1 = (int) (ylocations[l] + RANDOM () % y2 + 1); - else - y1 = (int) (ylocations[l] + 1); - - break; - } - case 4: - { /* bottom wall placement */ - x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; - if (x2 > 0) - x1 = (int) (xlocations[l] + RANDOM () % x2 + 1); - else - x1 = (int) (xlocations[l] + 1); - y1 = (int) ylocations[2 * layers - l - 1]; - break; - } + case 1: + { /* left hand wall */ + x1 = (int) xlocations[l]; + y2 = (int) (ylocations[2 * layers - l - 1] - ylocations[l] - 1); + if (y2 > 0) + y1 = (int) (ylocations[l] + rmg_rndm (y2) + 1); + else + y1 = (int) (ylocations[l] + 1); + break; + } + case 2: + { /* top wall placement */ + x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; + if (x2 > 0) + x1 = (int) (xlocations[l] + rmg_rndm (x2) + 1); + else + x1 = (int) (xlocations[l] + 1); + y1 = (int) ylocations[l]; + break; + } + case 3: + { /* right wall placement */ + x1 = (int) xlocations[2 * layers - l - 1]; + y2 = (int) ((-ylocations[l] + ylocations[2 * layers - l - 1])) - 1; + if (y2 > 0) + y1 = (int) (ylocations[l] + rmg_rndm (y2) + 1); + else + y1 = (int) (ylocations[l] + 1); + + break; + } + case 4: + { /* bottom wall placement */ + x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; + if (x2 > 0) + x1 = (int) (xlocations[l] + rmg_rndm (x2) + 1); + else + x1 = (int) (xlocations[l] + 1); + y1 = (int) ylocations[2 * layers - l - 1]; + break; + } } } - if (options & OPT_NO_DOORS) + + if (options & RMOPT_NO_DOORS) maze[x1][y1] = '#'; /* no door. */ else maze[x1][y1] = 'D'; /* write the door */ @@ -407,34 +403,31 @@ 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 = (RANDOM () % 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 & OPT_IRR_SPACE) /* randomly spaced */ + if (option & RMOPT_IRR_SPACE) /* randomly spaced */ { int x_spaces_available, y_spaces_available; @@ -449,10 +442,11 @@ float xpitch = 2, ypitch = 2; if (x_spaces_available > 0) - xpitch = 2 + (RANDOM () % x_spaces_available + RANDOM () % x_spaces_available + RANDOM () % 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 + (RANDOM () % y_spaces_available + RANDOM () % y_spaces_available + RANDOM () % 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; else @@ -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 & OPT_IRR_SPACE)) + + 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); } +