/* * static char *room_gen_onion_c = * "$Id: room_gen_onion.c,v 1.1.1.1 2006/02/03 07:14:22 root Exp $"; */ /* 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: char **map_gen_onion(int xsize, int ysize, int option, int layers); like this: regular random centered, linear onion bottom/right centered, nonlinear ######################### ######################### # # # # # ######## ########## # # ##################### # # # # # # # # # ###### ######## # # # # # # # # # # # # # ######## ######## # # # #### ###### # # # # # # # # # # # # # # # # # # # # # # ############ # # # # # # ########### ## # # # # # # # # # # # # # ################ # # # # # # ######### # # # # # # # # # # #################### # # # # # # # # # # # # # # ######################### ######################### */ int *free_x_list; int *free_y_list; #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); 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) { int i,j; /* allocate that array, set it up */ char **maze = (char **)calloc(sizeof(char*),xsize); for(i=0;i maxlayers) layers = maxlayers; if(layers == 0) layers = (RANDOM() % maxlayers)+1; xlocations = (float *) calloc(sizeof(float),2 * layers); ylocations = (float *) calloc(sizeof(float),2 * layers); /* place all the walls */ if(option & OPT_IRR_SPACE) /* randomly spaced */ { int x_spaces_available, y_spaces_available; /* the "extra" spaces available for spacing between layers */ 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; if(y_spaces_available>0) ypitch = 2 + (RANDOM()%y_spaces_available + RANDOM()%y_spaces_available + RANDOM()%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-=xpitch -2; y_spaces_available-=ypitch -2; } } if(!(option&OPT_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; ylocations[i] = ylocations[i-1] + ypitch; } } /* draw all the onion boxes. */ draw_onion(maze,xlocations,ylocations,layers); make_doors(maze,xlocations,ylocations,layers,option); } 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); /* place all the walls */ if(option & OPT_IRR_SPACE) /* randomly spaced */ { int x_spaces_available, y_spaces_available; /* the "extra" spaces available for spacing between layers */ 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; if(y_spaces_available>0) ypitch = 2 + (RANDOM()%y_spaces_available + RANDOM()%y_spaces_available + RANDOM()%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-=xpitch -2; y_spaces_available-=ypitch -2; } } if(!(option&OPT_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 ylocations[i]=ysize-1; } } /* draw all the onion boxes. */ draw_onion(maze,xlocations,ylocations,layers); make_doors(maze,xlocations,ylocations,layers,option); } /* draw_boxes: draws the lines in the maze defining the onion layers */ void draw_onion(char **maze,float *xlocations,float *ylocations, int layers) { int i,j,l; for(l=0;l 0) y1 = ylocations[l]+RANDOM() %y2 + 1; else y1 = ylocations[l]+1; break; } case 2: { /* top wall placement */ x2 = (int)( (-xlocations[l] + xlocations[2*layers-l-1]))-1; if (x2 > 0) x1 = xlocations[l]+RANDOM()%x2 + 1; else x1 = 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 = ylocations[l]+RANDOM() %y2 + 1; else y1 = ylocations[l]+1; break; } case 4: { /* bottom wall placement */ x2 = (int)( (-xlocations[l] + xlocations[2*layers-l-1]))-1; if (x2 > 0) x1 = xlocations[l]+RANDOM()%x2 + 1; else x1 = xlocations[l]+1; y1 = (int)ylocations[2*layers-l-1]; break; } } } if(options & OPT_NO_DOORS) maze[x1][y1] = '#'; /* no door. */ else maze[x1][y1] = 'D'; /* write the door */ } /* mark the center of the maze with a C */ 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); } 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); /* place all the walls */ if(option & OPT_IRR_SPACE) /* randomly spaced */ { int x_spaces_available, y_spaces_available; /* the "extra" spaces available for spacing between layers */ x_spaces_available = (xsize -2) - 3*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; if(y_spaces_available>0) ypitch = 2 + (RANDOM()%y_spaces_available + RANDOM()%y_spaces_available + RANDOM()%y_spaces_available)/3; if(i < layers) xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch; else xlocations[i] = xsize-1; if(i < layers) ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch; else ylocations[i] = ysize-1; x_spaces_available-=xpitch -2; y_spaces_available-=ypitch -2; } } if(!(option&OPT_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 ylocations[i]=ysize-1; } } /* draw all the onion boxes. */ draw_onion(maze,xlocations,ylocations,layers); make_doors(maze,xlocations,ylocations,layers,option); }