Crossfire Server, Branch 1.12  R12190
room_gen_spiral.c
Go to the documentation of this file.
00001 /*
00002     CrossFire, A Multiplayer game for X-windows
00003 
00004     Copyright (C) 1994 Mark Wedel
00005     Copyright (C) 1992 Frank Tore Johansen
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 
00021     The author can be reached via e-mail to mark@pyramid.com
00022 */
00023 
00024 
00031 #include <global.h>
00032 #include <random_map.h>
00033 
00038 #define RANDOM_OPTIONS 0  
00039 #define REGULAR_SPIRAL 1  
00040 #define FINE_SPIRAL 2     
00041 #define FIT_SPIRAL 4      
00042 #define MAX_SPIRAL_OPT 8  
00044 
00045 #include <math.h>
00046 
00047 #ifndef MIN
00048 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
00049 #endif
00050 #ifndef MAX
00051 #define MAX(x, y) (((x) < (y)) ? (y) : (x))
00052 #endif
00053 
00054 #define MAX_FINE .454545
00055 
00056 extern int surround_check(char **maze, int i, int j, int xsize, int ysize);
00057 
00068 char **map_gen_spiral(int xsize, int ysize, int option) {
00069     int i, j;
00070     float parm = 0;
00071     float x = 0, y = 0;
00072     int ic, jc;
00073     float SizeX, SizeY;
00074     float xscale, yscale;
00075 
00076     /* allocate that array, set it up */
00077     char **maze = (char **)calloc(sizeof(char *), xsize);
00078 
00079     for (i = 0; i < xsize; i++) {
00080         maze[i] = (char *)calloc(sizeof(char), ysize);
00081     }
00082 
00083     /* slightly easier to fill and then cut */
00084     for (i = 0; i < xsize; i++)
00085         for (j = 0; j < ysize; j++)
00086             maze[i][j] = '#';
00087 
00088     ic = xsize/2;
00089     jc = ysize/2;
00090     SizeX = xsize/2-2;
00091     SizeY = ysize/2-2;
00092 
00093     /* select random options if necessary */
00094     if (option == 0) {
00095         option = RANDOM()%MAX_SPIRAL_OPT;
00096     }
00097 
00098     /* the order in which these are evaluated matters*/
00099 
00100     /* the following two are mutually exclusive.
00101        pick one if they're both set. */
00102     if ((option&REGULAR_SPIRAL) && (option&FIT_SPIRAL)) {
00103         /* unset REGULAR_SPIRAL half the time */
00104         if (RANDOM()%2 && (option&REGULAR_SPIRAL))
00105             option -= REGULAR_SPIRAL;
00106         else
00107             option -= FIT_SPIRAL;
00108     }
00109 
00110     xscale = yscale = MAX_FINE;  /* fine spiral */
00111 
00112     /* choose the spiral pitch */
00113     if (!(option&FINE_SPIRAL)) {
00114         float pitch = (RANDOM()%5)/10.+10./22.;
00115 
00116         xscale = yscale = pitch;
00117     }
00118 
00119     if ((option&FIT_SPIRAL) && (xsize != ysize)) {
00120         if (xsize > ysize)
00121             xscale *= (float)xsize/(float)ysize;
00122         else
00123             yscale *= (float)ysize/(float)xsize;
00124     }
00125 
00126     if (option&REGULAR_SPIRAL) {
00127         float scale = MIN(xscale, yscale);
00128 
00129         xscale = yscale = scale;
00130     }
00131 
00132     /* cut out the spiral */
00133     while ((abs(x) < SizeX) && (abs(y) < SizeY)) {
00134         x = parm*cos(parm)*xscale;
00135         y = parm*sin(parm)*yscale;
00136         maze[(int)(ic+x)][(int)(jc+y)] = '\0';
00137         parm += 0.01;
00138     };
00139 
00140     maze[(int)(ic+x+0.5)][(int)(jc+y+0.5)] = '<';
00141 
00142     /* cut out the center in a 2x2 and place the center and downexit */
00143     maze[ic][jc+1] = '>';
00144     maze[ic][jc] = 'C';
00145 
00146     return maze;
00147 }
00148 
00159 void connect_spirals(int xsize, int ysize, int sym, char **layout) {
00160     int i, j, ic = xsize/2, jc = ysize/2;
00161 
00162     if (sym == X_SYM) {
00163         layout[ic][jc] = 0;
00164         /* go left from map center */
00165         for (i = ic-1, j = jc; i > 0 && layout[i][j] == '#'; i--)
00166             layout[i][j] = 0;
00167         /* go right */
00168         for (i = ic+1, j = jc; i < xsize-1 && layout[i][j] == '#'; i++)
00169             layout[i][j] = 0;
00170     }
00171 
00172     if (sym == Y_SYM) {
00173         layout[ic][jc] = 0;
00174         /* go up */
00175         for (i = ic, j = jc-1; j > 0 && layout[i][j] == '#'; j--)
00176             layout[i][j] = 0;
00177         /* go down */
00178         for (i = ic, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++)
00179             layout[i][j] = 0;
00180     }
00181 
00182     if (sym == XY_SYM) {
00183         /* go left from map center */
00184         layout[ic][jc/2] = 0;
00185         layout[ic/2][jc] = 0;
00186         layout[ic][jc/2+jc] = 0;
00187         layout[ic/2+ic][jc] = 0;
00188         for (i = ic-1, j = jc/2; i > 0 && layout[i][j] == '#'; i--) {
00189             layout[i][j+jc] = 0;
00190             layout[i][j] = 0;
00191         }
00192         /* go right */
00193         for (i = ic+1, j = jc/2; i < xsize-1 && layout[i][j] == '#'; i++) {
00194             layout[i][j+jc] = 0;
00195             layout[i][j] = 0;
00196         }
00197         /* go up */
00198         for (i = ic/2, j = jc-1; j > 0 && layout[i][j] == '#'; j--) {
00199             layout[i][j] = 0;
00200             layout[i+ic][j] = 0;
00201         }
00202         /* go down */
00203         for (i = ic/2, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++) {
00204             layout[i][j] = 0;
00205             layout[i+ic][j] = 0;
00206         }
00207     }
00208 
00209     /* get rid of bad doors. */
00210     for (i = 0; i < xsize; i++)
00211         for (j = 0; j < ysize; j++) {
00212             if (layout[i][j] == 'D') { /* remove bad door. */
00213                 int si = surround_check(layout, i, j, xsize, ysize);
00214                 if (si != 3 && si != 12) {
00215                     layout[i][j] = 0;
00216                     /* back up and recheck any nearby doors */
00217                     i = 0;
00218                     j = 0;
00219                 }
00220             }
00221         }
00222 }