/* peterm@langmuir.eecs.berkeley.edu: this function generates a random blocked maze with the property that there is only one path from one spot to any other, and there is always a path from one spot to any other. input: xsize, ysize; output: a char** array with # and . for closed and open respectively. a char value of 0 represents a blank space: a '#' is a wall. */ /* we need to maintain a list of wall points to generate reasonable mazes: a straightforward recursive random walk maze generator would generate a map with a trivial circle-the-outer-wall solution */ #include #include /*#include */ #include #include /* this include solely, and only, is needed for the definition of RANDOM */ /* global variables that everyone needs: don't want to pass them in as parameters every time. */ int *wall_x_list=0; int *wall_y_list=0; int wall_free_size=0; /* heuristically, we need to change wall_chance based on the size of the maze. */ int wall_chance; /* the outsize interface routine: accepts sizes, returns a char ** maze. option is a flag for either a sparse or a full maze. Sparse mazes have sizable rooms. option = 1, full, 0, sparse.*/ char **maze_gen(int xsize, int ysize,int option) { int i,j; /* allocate that array, set it up */ char **maze = (char **)calloc(sizeof(char*),xsize); for(i=0;i 0) { pop_wall_point(&i,&j); if(option) fill_maze_full(maze,i,j,xsize,ysize); else fill_maze_sparse(maze,i,j,xsize,ysize); } /* clean up our intermediate data structures. */ free(wall_x_list); free(wall_y_list); return maze; } /* the free wall points are those outer points which aren't corners or near corners, and don't have a maze wall growing out of them already. */ void make_wall_free_list(int xsize, int ysize) { int i,j,count; count = 0; /* entries already placed in the free list */ /*allocate it*/ if(wall_free_size < 0) return; wall_x_list = (int *) calloc(sizeof(int),wall_free_size); wall_y_list = (int *) calloc(sizeof(int),wall_free_size); /* top and bottom wall */ for(i = 2; i 2 && xc < xsize-2) /* it is valid to look up */ { int cleartest = (int) maze[xc][yc+1] + (int)maze[xc-1][yc+1] + (int) maze[xc+1][yc+1]; cleartest += (int) maze[xc][yc+2] + (int)maze[xc-1][yc+2] + (int) maze[xc+1][yc+2]; if(cleartest == 0) { dirlist[count] = 1; count++; } } /* look down */ if(yc > 2 && xc > 2 && xc < xsize-2) /* it is valid to look down */ { int cleartest = (int) maze[xc][yc-1] + (int)maze[xc-1][yc-1] + (int) maze[xc+1][yc-1]; cleartest += (int) maze[xc][yc-2] + (int)maze[xc-1][yc-2] + (int) maze[xc+1][yc-2]; if(cleartest == 0) { dirlist[count] = 2; count++; } } /* look right */ if(xc < xsize- 2 && yc > 2 && yc < ysize-2) /* it is valid to look left */ { int cleartest = (int) maze[xc+1][yc] + (int)maze[xc+1][yc-1] + (int) maze[xc+1][yc+1]; cleartest += (int) maze[xc+2][yc] + (int)maze[xc+2][yc-1] + (int) maze[xc+2][yc+1]; if(cleartest == 0) { dirlist[count] = 3; count++; } } /* look left */ if(xc > 2 && yc > 2 && yc < ysize-2) /* it is valid to look down */ { int cleartest = (int) maze[xc-1][yc] + (int)maze[xc-1][yc-1] + (int) maze[xc-1][yc+1]; cleartest += (int) maze[xc-2][yc] + (int)maze[xc-2][yc-1] + (int) maze[xc-2][yc+1]; if(cleartest == 0) { dirlist[count] = 4; count++; } } if(count==0) return -1; /* failed to find any clear points */ /* choose a random direction */ if(count > 1) count = RANDOM() % count; else count=0; switch(dirlist[count]) { case 1: /* up */ { *y = yc +1; *x = xc; break; }; case 2: /* down */ { *y = yc-1; *x = xc; break; }; case 3: /* right */ { *y = yc; *x = xc+1; break; } case 4: /* left */ { *x = xc-1; *y = yc; break; } default: /* ??? */ { return -1; } } return 1; } /* recursive routine which will fill every available space in the maze with walls*/ void fill_maze_full(char **maze, int x, int y, int xsize, int ysize ) { int xc,yc; /* write a wall here */ maze[x][y] = '#'; /* decide if we're going to pick from the wall_free_list */ if(RANDOM()%4 && wall_free_size > 0) { pop_wall_point(&xc,&yc); fill_maze_full(maze,xc,yc,xsize,ysize); } /* change the if to a while for a complete maze. */ while(find_free_point(maze,&xc,&yc,x,y,xsize,ysize)!=-1) { fill_maze_full(maze,xc,yc,xsize,ysize); } } /* recursive routine which will fill much of the maze, but will leave some free spots (possibly large) toward the center.*/ void fill_maze_sparse(char **maze, int x, int y, int xsize, int ysize ) { int xc,yc; /* write a wall here */ maze[x][y] = '#'; /* decide if we're going to pick from the wall_free_list */ if(RANDOM()%4 && wall_free_size > 0) { pop_wall_point(&xc,&yc); fill_maze_sparse(maze,xc,yc,xsize,ysize); } /* change the if to a while for a complete maze. */ if(find_free_point(maze,&xc,&yc,x,y,xsize,ysize)!=-1) { fill_maze_sparse(maze,xc,yc,xsize,ysize); } }