|
Atrinik Server 2.5
|
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 00034 #include <global.h> 00035 00037 typedef struct free_walls_struct 00038 { 00040 int *wall_x_list; 00041 00043 int *wall_y_list; 00044 00046 int wall_free_size; 00047 } free_walls_struct; 00048 00049 static void fill_maze_full(char **maze, int x, int y ,int xsize, int ysize, free_walls_struct *free_walls); 00050 static void fill_maze_sparse(char **maze, int x, int y, int xsize, int ysize, free_walls_struct *free_walls); 00051 static void make_wall_free_list(int xsize, int ysize, free_walls_struct *free_walls); 00052 static void pop_wall_point(int *x, int *y, free_walls_struct *free_walls); 00053 static int find_free_point(char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize); 00054 00065 char **maze_gen(int xsize, int ysize, int option) 00066 { 00067 int i, j; 00068 struct free_walls_struct free_walls; 00069 /* allocate that array, set it up */ 00070 char **maze = (char **) calloc(sizeof(char *), xsize); 00071 00072 for (i = 0; i < xsize; i++) 00073 { 00074 maze[i] = (char *) calloc(sizeof(char), ysize); 00075 } 00076 00077 /* Write the outer walls */ 00078 for (i = 0; i < xsize; i++) 00079 { 00080 maze[i][0] = maze[i][ysize - 1] = '#'; 00081 } 00082 00083 for (j = 0;j < ysize; j++) 00084 { 00085 maze[0][j] = maze[xsize - 1][j] = '#'; 00086 } 00087 00088 /* Find how many free wall spots there are */ 00089 free_walls.wall_free_size = 2 * (xsize - 4) + 2 * (ysize - 4); 00090 00091 free_walls.wall_x_list = NULL; 00092 free_walls.wall_y_list = NULL; 00093 00094 make_wall_free_list(xsize, ysize, &free_walls); 00095 00096 /* Return the empty maze */ 00097 if (free_walls.wall_free_size <= 0) 00098 { 00099 return maze; 00100 } 00101 00102 /* recursively generate the walls of the maze */ 00103 while (free_walls.wall_free_size > 0) 00104 { 00105 /* first pop a random starting point */ 00106 pop_wall_point(&i, &j, &free_walls); 00107 00108 if (option) 00109 { 00110 fill_maze_full(maze, i, j, xsize, ysize, &free_walls); 00111 } 00112 else 00113 { 00114 fill_maze_sparse(maze, i, j, xsize, ysize, &free_walls); 00115 } 00116 } 00117 00118 /* clean up our intermediate data structures. */ 00119 free(free_walls.wall_x_list); 00120 free(free_walls.wall_y_list); 00121 00122 return maze; 00123 } 00124 00134 static void make_wall_free_list(int xsize, int ysize, free_walls_struct *free_walls) 00135 { 00136 int i, j, count = 0; 00137 00138 if (free_walls->wall_free_size < 0) 00139 { 00140 return; 00141 } 00142 00143 /* allocate it */ 00144 free_walls->wall_x_list = (int *) calloc(sizeof(int), free_walls->wall_free_size); 00145 free_walls->wall_y_list = (int *) calloc(sizeof(int), free_walls->wall_free_size); 00146 00147 /* top and bottom wall */ 00148 for (i = 2; i < xsize - 2; i++) 00149 { 00150 free_walls->wall_x_list[count] = i; 00151 free_walls->wall_y_list[count] = 0; 00152 count++; 00153 00154 free_walls->wall_x_list[count] = i; 00155 free_walls->wall_y_list[count] = ysize - 1; 00156 count++; 00157 } 00158 00159 /* left and right wall */ 00160 for (j = 2; j < ysize - 2; j++) 00161 { 00162 free_walls->wall_x_list[count] = 0; 00163 free_walls->wall_y_list[count] = j; 00164 count++; 00165 00166 free_walls->wall_x_list[count] = xsize - 1; 00167 free_walls->wall_y_list[count] = j; 00168 count++; 00169 } 00170 } 00171 00177 static void pop_wall_point(int *x, int *y, free_walls_struct *free_walls) 00178 { 00179 int i = RANDOM() % free_walls->wall_free_size; 00180 00181 *x = free_walls->wall_x_list[i]; 00182 *y = free_walls->wall_y_list[i]; 00183 00184 /* Write the last array point here */ 00185 free_walls->wall_x_list[i] = free_walls->wall_x_list[free_walls->wall_free_size - 1]; 00186 free_walls->wall_y_list[i] = free_walls->wall_y_list[free_walls->wall_free_size - 1]; 00187 00188 free_walls->wall_free_size--; 00189 } 00190 00204 static int find_free_point(char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize) 00205 { 00206 /* we will randomly pick from this list, 1=up,2=down,3=right,4=left */ 00207 int dirlist[4]; 00208 /* # elements in dirlist */ 00209 int count = 0; 00210 00211 /* look up */ 00212 if (yc < ysize - 2 && xc > 2 && xc < xsize - 2) 00213 { 00214 int cleartest = (int) maze[xc][yc + 1] + (int) maze[xc - 1][yc + 1] + (int) maze[xc + 1][yc + 1]; 00215 00216 cleartest += (int) maze[xc][yc + 2] + (int) maze[xc - 1][yc + 2] + (int) maze[xc + 1][yc + 2]; 00217 00218 if (cleartest == 0) 00219 { 00220 dirlist[count] = 1; 00221 count++; 00222 } 00223 } 00224 00225 /* look down */ 00226 if (yc > 2 && xc > 2 && xc < xsize - 2) 00227 { 00228 int cleartest = (int) maze[xc][yc - 1] + (int) maze[xc - 1][yc - 1] + (int) maze[xc + 1][yc - 1]; 00229 00230 cleartest += (int) maze[xc][yc - 2] + (int) maze[xc - 1][yc - 2] + (int) maze[xc + 1][yc - 2]; 00231 00232 if (cleartest == 0) 00233 { 00234 dirlist[count] = 2; 00235 count++; 00236 } 00237 } 00238 00239 /* look right */ 00240 if (xc < xsize - 2 && yc > 2 && yc < ysize - 2) 00241 { 00242 int cleartest = (int) maze[xc + 1][yc] + (int) maze[xc + 1][yc - 1] + (int) maze[xc + 1][yc + 1]; 00243 00244 cleartest += (int) maze[xc + 2][yc] + (int) maze[xc + 2][yc - 1] + (int) maze[xc + 2][yc + 1]; 00245 00246 if (cleartest == 0) 00247 { 00248 dirlist[count] = 3; 00249 count++; 00250 } 00251 } 00252 00253 /* look left */ 00254 if (xc > 2 && yc > 2 && yc < ysize - 2) 00255 { 00256 int cleartest = (int) maze[xc - 1][yc] + (int) maze[xc - 1][yc - 1] + (int) maze[xc - 1][yc + 1]; 00257 00258 cleartest += (int) maze[xc - 2][yc] + (int) maze[xc - 2][yc - 1] + (int) maze[xc - 2][yc + 1]; 00259 00260 if (cleartest == 0) 00261 { 00262 dirlist[count] = 4; 00263 count++; 00264 } 00265 } 00266 00267 /* Failed to find any clear points */ 00268 if (count == 0) 00269 { 00270 return -1; 00271 } 00272 00273 /* choose a random direction */ 00274 if (count > 1) 00275 { 00276 count = RANDOM() % count; 00277 } 00278 else 00279 { 00280 count = 0; 00281 } 00282 00283 switch (dirlist[count]) 00284 { 00285 case 1: 00286 *y = yc + 1; 00287 *x = xc; 00288 00289 break; 00290 00291 case 2: 00292 *y = yc - 1; 00293 *x = xc; 00294 00295 break; 00296 00297 case 3: 00298 *y = yc; 00299 *x = xc + 1; 00300 00301 break; 00302 00303 case 4: 00304 *x = xc - 1; 00305 *y = yc; 00306 00307 break; 00308 00309 default: 00310 return -1; 00311 } 00312 00313 return 1; 00314 } 00315 00326 static void fill_maze_full(char **maze, int x, int y, int xsize, int ysize, free_walls_struct *free_walls) 00327 { 00328 int xc, yc; 00329 00330 /* Write a wall here */ 00331 maze[x][y] = '#'; 00332 00333 /* Decide if we're going to pick from the wall_free_list */ 00334 if (RANDOM() % 4 && free_walls->wall_free_size > 0) 00335 { 00336 pop_wall_point(&xc, &yc, free_walls); 00337 fill_maze_full(maze, xc, yc, xsize, ysize, free_walls); 00338 } 00339 00340 /* Change the if to a while for a complete maze. */ 00341 while (find_free_point(maze, &xc, &yc, x, y, xsize, ysize) != -1) 00342 { 00343 fill_maze_full(maze, xc, yc, xsize, ysize, free_walls); 00344 } 00345 } 00346 00356 static void fill_maze_sparse(char **maze, int x, int y, int xsize, int ysize, free_walls_struct *free_walls) 00357 { 00358 int xc, yc; 00359 00360 /* Write a wall here */ 00361 maze[x][y] = '#'; 00362 00363 /* Decide if we're going to pick from the wall_free_list */ 00364 if (RANDOM() % 4 && free_walls->wall_free_size > 0) 00365 { 00366 pop_wall_point(&xc, &yc, free_walls); 00367 fill_maze_sparse(maze, xc, yc, xsize, ysize, free_walls); 00368 } 00369 00370 /* Change the if to a while for a complete maze. */ 00371 if (find_free_point(maze, &xc, &yc, x, y, xsize, ysize) != -1) 00372 { 00373 fill_maze_sparse(maze, xc, yc, xsize, ysize, free_walls); 00374 } 00375 }
1.7.4