Atrinik Server 2.5
random_maps/room_gen_spiral.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00036 #define RANDOM_OPTIONS  0
00037 
00038 #define REGULAR_SPIRAL  1
00039 
00040 #define FINE_SPIRAL     2
00041 
00042 #define FIT_SPIRAL      4
00043 
00044 #define MAX_SPIRAL_OPT  8
00045 
00047 #include <math.h>
00048 
00049 #ifndef MIN
00050 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
00051 #endif
00052 
00053 #ifndef MAX
00054 #define MAX(x, y) (((x) < (y)) ? (y) : (x))
00055 #endif
00056 
00057 #define MINDIST 3
00058 
00059 #define MAX_FINE .454545
00060 
00061 extern int surround_check(char **maze, int i, int j, int xsize, int ysize);
00062 
00069 char **map_gen_spiral(int xsize, int ysize, int option)
00070 {
00071     int i, j, ic, jc;
00072     float parm = 0, x = 0, y = 0, SizeX, SizeY, xscale,yscale;
00073 
00074     /* Allocate that array, set it up */
00075     char **maze = (char **) calloc(sizeof(char *), xsize);
00076 
00077     for (i = 0; i < xsize; i++)
00078     {
00079         maze[i] = (char *) calloc(sizeof(char), ysize);
00080     }
00081 
00082     /* Slightly easier to fill and then cut */
00083     for (i = 0; i < xsize; i++)
00084     {
00085         for (j = 0; j < ysize; j++)
00086         {
00087             maze[i][j] = '#';
00088         }
00089     }
00090 
00091     ic = xsize / 2;
00092     jc = ysize / 2;
00093 
00094     SizeX = (float) xsize / 2.0f - 2.0f;
00095     SizeY = (float) ysize / 2.0f - 2.0f;
00096 
00097     /* Select random options if necessary */
00098     if (option == 0)
00099     {
00100         option = RANDOM() % MAX_SPIRAL_OPT;
00101     }
00102 
00103     /* the order in which these are evaluated matters */
00104 
00105     /* the following two are mutually exclusive.
00106        pick one if they're both set. */
00107     if ((option & REGULAR_SPIRAL) && (option & FIT_SPIRAL))
00108     {
00109         /* unset REGULAR_SPIRAL half the time */
00110         if (RANDOM() % 2 && (option & REGULAR_SPIRAL))
00111         {
00112             option -= REGULAR_SPIRAL;
00113         }
00114         else
00115         {
00116             option -= FIT_SPIRAL;
00117         }
00118     }
00119 
00120     /* fine spiral */
00121     xscale = yscale= ( float) MAX_FINE;
00122 
00123     /* choose the spiral pitch */
00124     if (!(option & FINE_SPIRAL))
00125     {
00126         float pitch = (float) (RANDOM() % 5) / 10.0f + 10.0f / 22.0f;
00127 
00128         xscale = yscale = pitch;
00129     }
00130 
00131     if ((option & FIT_SPIRAL) && (xsize != ysize))
00132     {
00133         if (xsize > ysize)
00134         {
00135             xscale *= (float) xsize / (float) ysize;
00136         }
00137         else
00138         {
00139             yscale *= (float) ysize / (float) xsize;
00140         }
00141     }
00142 
00143     if (option & REGULAR_SPIRAL)
00144     {
00145         float scale = MIN(xscale, yscale);
00146         xscale = yscale = scale;
00147     }
00148 
00149     /* cut out the spiral */
00150     while ((FABS(x) < SizeX) && (FABS(y) < SizeY))
00151     {
00152         x = parm * (float) cos((double) parm) * xscale;
00153         y = parm * (float) sin((double) parm) * yscale;
00154 
00155         maze[(int) (ic + x)][(int) (jc + y)] = '\0';
00156 
00157         parm += 0.01f;
00158     }
00159 
00160     maze[(int) (ic + x + 0.5)][(int) (jc + y + 0.5)] = '<';
00161 
00162     /* Cut out the center in a 2x2 and place the center and downexit */
00163     maze[ic][jc + 1] = '>';
00164     maze[ic][jc] = 'C';
00165 
00166     return maze;
00167 }
00168 
00176 void connect_spirals(int xsize, int ysize, int sym, char **layout)
00177 {
00178     int i, j, ic = xsize / 2, jc = ysize / 2;
00179 
00180     if (sym == X_SYM)
00181     {
00182         layout[ic][jc] = 0;
00183 
00184         /* go left from map center */
00185         for (i = ic - 1, j = jc; i > 0 && layout[i][j] == '#'; i--)
00186         {
00187             layout[i][j] = 0;
00188         }
00189 
00190         /* go right */
00191         for (i = ic + 1, j = jc; i < xsize - 1 && layout[i][j] == '#'; i++)
00192         {
00193             layout[i][j] = 0;
00194         }
00195     }
00196 
00197     if (sym == Y_SYM)
00198     {
00199         layout[ic][jc] = 0;
00200 
00201         /* go up */
00202         for (i = ic, j = jc - 1; j > 0 && layout[i][j] == '#'; j--)
00203         {
00204             layout[i][j] = 0;
00205         }
00206 
00207         /* go down */
00208         for (i = ic, j = jc + 1; j < ysize - 1 && layout[i][j] == '#'; j++)
00209         {
00210             layout[i][j] = 0;
00211         }
00212     }
00213 
00214     if (sym == XY_SYM)
00215     {
00216         layout[ic][jc / 2] = 0;
00217         layout[ic / 2][jc] = 0;
00218         layout[ic][jc / 2 + jc] = 0;
00219         layout[ic / 2 + ic][jc] = 0;
00220 
00221         /* go left from map center */
00222         for (i = ic - 1, j = jc / 2; i > 0 && layout[i][j] == '#'; i--)
00223         {
00224             layout[i][j + jc] = 0;
00225             layout[i][j] = 0;
00226         }
00227 
00228         /* go right */
00229         for (i = ic + 1, j = jc / 2; i < xsize - 1 && layout[i][j] == '#'; i++)
00230         {
00231             layout[i][j + jc] = 0;
00232             layout[i][j] = 0;
00233         }
00234 
00235         /* go up */
00236         for (i = ic / 2, j = jc - 1; j > 0 && layout[i][j] == '#'; j--)
00237         {
00238             layout[i][j] = 0;
00239             layout[i + ic][j] = 0;
00240         }
00241 
00242         /* go down */
00243         for (i = ic / 2, j = jc + 1; j < ysize - 1 && layout[i][j] == '#'; j++)
00244         {
00245             layout[i][j] = 0;
00246             layout[i + ic][j] = 0;
00247         }
00248     }
00249 
00250     /* Get rid of bad doors. */
00251     for (i = 0; i < xsize; i++)
00252     {
00253         for (j = 0; j < ysize; j++)
00254         {
00255             /* Remove bad door. */
00256             if (layout[i][j] == 'D')
00257             {
00258                 int si = surround_check(layout, i, j, xsize, ysize);
00259 
00260                 if (si != 3 && si != 12)
00261                 {
00262                     layout[i][j] = 0;
00263 
00264                     /* Back up and recheck any nearby doors */
00265                     i = 0;
00266                     j = 0;
00267                 }
00268             }
00269         }
00270     }
00271 }