--- deliantra/server/random_maps/room_gen_onion.C 2007/01/18 19:42:10 1.9 +++ deliantra/server/random_maps/room_gen_onion.C 2008/05/04 14:12:37 1.16 @@ -1,28 +1,26 @@ /* - * CrossFire, A Multiplayer game for X-windows + * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team - * Copyright (C) 2001 Mark Wedel & Crossfire Development Team - * Copyright (C) 1992 Frank Tore Johansen + * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992,2007 Frank Tore Johansen * - * This program is free software; you can redistribute it and/or modify + * 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 2 of the License, or + * 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 + * 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 + * along with this program. If not, see . + * + * The authors can be reached via e-mail to */ - /* The onion room generator: Onion rooms are like this: @@ -61,27 +59,23 @@ 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); - 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; @@ -93,23 +87,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) @@ -118,27 +106,26 @@ bottom_centered_onion (maze, xsize, ysize, option, layers); else if (option & RMOPT_CENTERED) centered_onion (maze, xsize, ysize, option, layers); - - return maze; } 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; + 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 & RMOPT_IRR_SPACE) /* randomly spaced */ @@ -149,17 +136,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); @@ -167,14 +154,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; @@ -183,29 +173,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 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; + 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 & RMOPT_IRR_SPACE) /* randomly spaced */ @@ -216,38 +208,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 & 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 @@ -260,11 +257,11 @@ 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_onion (char **maze, float *xlocations, float *ylocations, int layers) { @@ -303,14 +300,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 = RANDOM () % freedoms + 1; + which_wall = rmg_rndm (freedoms) + 1; for (l = 0; l < layers; l++) { if (options & RMOPT_LINEAR) @@ -345,7 +346,7 @@ } else { /* random door placement. */ - which_wall = RANDOM () % freedoms + 1; + which_wall = rmg_rndm (freedoms) + 1; switch (which_wall) { case 1: @@ -353,7 +354,7 @@ x1 = (int) xlocations[l]; y2 = (int) (ylocations[2 * layers - l - 1] - ylocations[l] - 1); if (y2 > 0) - y1 = (int) (ylocations[l] + RANDOM () % y2 + 1); + y1 = (int) (ylocations[l] + rmg_rndm (y2) + 1); else y1 = (int) (ylocations[l] + 1); break; @@ -362,7 +363,7 @@ { /* top wall placement */ x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; if (x2 > 0) - x1 = (int) (xlocations[l] + RANDOM () % x2 + 1); + x1 = (int) (xlocations[l] + rmg_rndm (x2) + 1); else x1 = (int) (xlocations[l] + 1); y1 = (int) ylocations[l]; @@ -373,7 +374,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] + RANDOM () % y2 + 1); + y1 = (int) (ylocations[l] + rmg_rndm (y2) + 1); else y1 = (int) (ylocations[l] + 1); @@ -383,7 +384,7 @@ { /* bottom wall placement */ x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; if (x2 > 0) - x1 = (int) (xlocations[l] + RANDOM () % x2 + 1); + x1 = (int) (xlocations[l] + rmg_rndm (x2) + 1); else x1 = (int) (xlocations[l] + 1); y1 = (int) ylocations[2 * layers - l - 1]; @@ -392,6 +393,7 @@ } } + if (options & RMOPT_NO_DOORS) maze[x1][y1] = '#'; /* no door. */ else @@ -402,31 +404,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 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; + 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 & RMOPT_IRR_SPACE) /* randomly spaced */ @@ -444,10 +443,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 @@ -457,25 +457,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 @@ -488,4 +492,7 @@ draw_onion (maze, xlocations, ylocations, layers); make_doors (maze, xlocations, ylocations, layers, option); + sfree (xlocations, 2 * layers); + sfree (ylocations, 2 * layers); } +