00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00058 #include <stdlib.h>
00059 #include <global.h>
00060 #include <random_map.h>
00061
00062 #ifndef MIN
00063 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
00064 #endif
00065
00066 void centered_onion(char **maze, int xsize, int ysize, int option, int layers);
00067 void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers);
00068 void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers);
00069
00070 void draw_onion(char **maze, float *xlocations, float *ylocations, int layers);
00071 void make_doors(char **maze, float *xlocations, float *ylocations, int layers, int options);
00072
00085 char **map_gen_onion(int xsize, int ysize, int option, int layers) {
00086 int i, j;
00087
00088
00089 char **maze = (char **)calloc(sizeof(char *), xsize);
00090 for (i = 0; i < xsize; i++) {
00091 maze[i] = (char *)calloc(sizeof(char), ysize);
00092 }
00093
00094
00095 if (option == 0) {
00096 switch (RANDOM()%3) {
00097 case 0:
00098 option |= OPT_CENTERED;
00099 break;
00100
00101 case 1:
00102 option |= OPT_BOTTOM_C;
00103 break;
00104
00105 case 2:
00106 option |= OPT_BOTTOM_R;
00107 break;
00108 }
00109 if (RANDOM()%2)
00110 option |= OPT_LINEAR;
00111 if (RANDOM()%2)
00112 option |= OPT_IRR_SPACE;
00113 }
00114
00115
00116 if (!(option&OPT_WALL_OFF)) {
00117 for (i = 0; i < xsize; i++)
00118 maze[i][0] = maze[i][ysize-1] = '#';
00119 for (j = 0; j < ysize; j++)
00120 maze[0][j] = maze[xsize-1][j] = '#';
00121 };
00122
00123 if (option&OPT_WALLS_ONLY)
00124 return maze;
00125
00126
00127 if (option&OPT_BOTTOM_R)
00128 bottom_right_centered_onion(maze, xsize, ysize, option, layers);
00129 else if (option&OPT_BOTTOM_C)
00130 bottom_centered_onion(maze, xsize, ysize, option, layers);
00131 else if (option&OPT_CENTERED)
00132 centered_onion(maze, xsize, ysize, option, layers);
00133
00134 return maze;
00135 }
00136
00149 void centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
00150 int i, maxlayers;
00151 float *xlocations;
00152 float *ylocations;
00153
00154 maxlayers = (MIN(xsize, ysize)-2)/5;
00155 if (!maxlayers)
00156 return;
00157 if (layers > maxlayers)
00158 layers = maxlayers;
00159 if (layers == 0)
00160 layers = (RANDOM()%maxlayers)+1;
00161 xlocations = (float *)calloc(sizeof(float), 2*layers);
00162 ylocations = (float *)calloc(sizeof(float), 2*layers);
00163
00164
00165 if (option&OPT_IRR_SPACE) {
00166 int x_spaces_available, y_spaces_available;
00167
00168 x_spaces_available = (xsize-2)-6*layers+1;
00169 y_spaces_available = (ysize-2)-6*layers+1;
00170
00171
00172 for (i = 0; i < 2*layers; i++) {
00173 float xpitch = 2, ypitch = 2;
00174
00175 if (x_spaces_available > 0)
00176 xpitch = 2
00177 +(RANDOM()%x_spaces_available
00178 +RANDOM()%x_spaces_available
00179 +RANDOM()%x_spaces_available)/3;
00180
00181 if (y_spaces_available > 0)
00182 ypitch = 2
00183 +(RANDOM()%y_spaces_available
00184 +RANDOM()%y_spaces_available
00185 +RANDOM()%y_spaces_available)/3;
00186 xlocations[i] = ((i > 0) ? xlocations[i-1] : 0)+xpitch;
00187 ylocations[i] = ((i > 0) ? ylocations[i-1] : 0)+ypitch;
00188 x_spaces_available -= xpitch-2;
00189 y_spaces_available -= ypitch-2;
00190 }
00191
00192 }
00193 if (!(option&OPT_IRR_SPACE)) {
00194
00195 float xpitch, ypitch;
00196
00197 xpitch = (xsize-2.0)/(2.0*layers+1);
00198 ypitch = (ysize-2.0)/(2.0*layers+1);
00199 xlocations[0] = xpitch;
00200 ylocations[0] = ypitch;
00201 for (i = 1; i < 2*layers; i++) {
00202 xlocations[i] = xlocations[i-1]+xpitch;
00203 ylocations[i] = ylocations[i-1]+ypitch;
00204 }
00205 }
00206
00207
00208 draw_onion(maze, xlocations, ylocations, layers);
00209 make_doors(maze, xlocations, ylocations, layers, option);
00210 }
00211
00224 void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
00225 int i, maxlayers;
00226 float *xlocations;
00227 float *ylocations;
00228
00229 maxlayers = (MIN(xsize, ysize)-2)/5;
00230 if (!maxlayers)
00231 return;
00232 if (layers > maxlayers)
00233 layers = maxlayers;
00234 if (layers == 0)
00235 layers = (RANDOM()%maxlayers)+1;
00236 xlocations = (float *)calloc(sizeof(float), 2*layers);
00237 ylocations = (float *)calloc(sizeof(float), 2*layers);
00238
00239
00240 if (option&OPT_IRR_SPACE) {
00241 int x_spaces_available, y_spaces_available;
00242
00243 x_spaces_available = (xsize-2)-6*layers+1;
00244 y_spaces_available = (ysize-2)-3*layers+1;
00245
00246
00247 for (i = 0; i < 2*layers; i++) {
00248 float xpitch = 2, ypitch = 2;
00249
00250 if (x_spaces_available > 0)
00251 xpitch = 2
00252 +(RANDOM()%x_spaces_available
00253 +RANDOM()%x_spaces_available
00254 +RANDOM()%x_spaces_available)/3;
00255
00256 if (y_spaces_available > 0)
00257 ypitch = 2
00258 +(RANDOM()%y_spaces_available
00259 +RANDOM()%y_spaces_available
00260 +RANDOM()%y_spaces_available)/3;
00261 xlocations[i] = ((i > 0) ? xlocations[i-1] : 0)+xpitch;
00262 if (i < layers)
00263 ylocations[i] = ((i > 0) ? ylocations[i-1] : 0)+ypitch;
00264 else
00265 ylocations[i] = ysize-1;
00266 x_spaces_available -= xpitch-2;
00267 y_spaces_available -= ypitch-2;
00268 }
00269
00270 }
00271
00272 if (!(option&OPT_IRR_SPACE)) {
00273
00274 float xpitch, ypitch;
00275
00276 xpitch = (xsize-2.0)/(2.0*layers+1);
00277 ypitch = (ysize-2.0)/(layers+1);
00278 xlocations[0] = xpitch;
00279 ylocations[0] = ypitch;
00280 for (i = 1; i < 2*layers; i++) {
00281 xlocations[i] = xlocations[i-1]+xpitch;
00282 if (i < layers)
00283 ylocations[i] = ylocations[i-1]+ypitch;
00284 else
00285 ylocations[i] = ysize-1;
00286 }
00287 }
00288
00289
00290 draw_onion(maze, xlocations, ylocations, layers);
00291 make_doors(maze, xlocations, ylocations, layers, option);
00292 }
00293
00306 void draw_onion(char **maze, float *xlocations, float *ylocations, int layers) {
00307 int i, j, l;
00308
00309 for (l = 0; l < layers; l++) {
00310 int x1, x2, y1, y2;
00311
00312
00313 y1 = (int)ylocations[l];
00314 y2 = (int)ylocations[2*layers-l-1];
00315 for (i = (int)xlocations[l]; i <= (int)xlocations[2*layers-l-1]; i++) {
00316 maze[i][y1] = '#';
00317 maze[i][y2] = '#';
00318 }
00319
00320
00321 x1 = (int)xlocations[l];
00322 x2 = (int)xlocations[2*layers-l-1];
00323 for (j = (int)ylocations[l]; j <= (int)ylocations[2*layers-l-1]; j++) {
00324 maze[x1][j] = '#';
00325 maze[x2][j] = '#';
00326 }
00327 }
00328 }
00329
00344 void make_doors(char **maze, float *xlocations, float *ylocations, int layers, int options) {
00345 int freedoms;
00346 int which_wall;
00347 int l, x1 = 0, x2, y1 = 0, y2;
00348
00349 freedoms = 4;
00350 if (options&OPT_BOTTOM_C)
00351 freedoms = 3;
00352 if (options&OPT_BOTTOM_R)
00353 freedoms = 2;
00354 if (layers <= 0)
00355 return;
00356
00357
00358 which_wall = RANDOM()%freedoms+1;
00359 for (l = 0; l < layers; l++) {
00360 if (options&OPT_LINEAR) {
00361 switch (which_wall) {
00362 case 1: {
00363 x1 = (int)xlocations[l];
00364 y1 = (int)((ylocations[l]+ylocations[2*layers-l-1])/2);
00365 break;
00366 }
00367
00368 case 2: {
00369 x1 = (int)((xlocations[l]+xlocations[2*layers-l-1])/2);
00370 y1 = (int)ylocations[l];
00371 break;
00372 }
00373
00374 case 3: {
00375 x1 = (int)xlocations[2*layers-l-1];
00376 y1 = (int)((ylocations[l]+ylocations[2*layers-l-1])/2);
00377 break;
00378 }
00379
00380 case 4: {
00381 x1 = (int)((xlocations[l]+xlocations[2*layers-l-1])/2);
00382 y1 = (int)ylocations[2*layers-l-1];
00383 break;
00384 }
00385 }
00386 } else {
00387 which_wall = RANDOM()%freedoms+1;
00388 switch (which_wall) {
00389 case 1: {
00390 x1 = (int)xlocations[l];
00391 y2 = ylocations[2*layers-l-1]-ylocations[l]-1;
00392 if (y2 > 0)
00393 y1 = ylocations[l]+RANDOM()%y2+1;
00394 else
00395 y1 = ylocations[l]+1;
00396 break;
00397 }
00398
00399 case 2: {
00400 x2 = (int)((-xlocations[l]+xlocations[2*layers-l-1]))-1;
00401 if (x2 > 0)
00402 x1 = xlocations[l]+RANDOM()%x2+1;
00403 else
00404 x1 = xlocations[l]+1;
00405 y1 = (int)ylocations[l];
00406 break;
00407 }
00408
00409 case 3: {
00410 x1 = (int)xlocations[2*layers-l-1];
00411 y2 = (int)((-ylocations[l]+ylocations[2*layers-l-1]))-1;
00412 if (y2 > 0)
00413 y1 = ylocations[l]+RANDOM()%y2+1;
00414 else
00415 y1 = ylocations[l]+1;
00416 break;
00417 }
00418
00419 case 4: {
00420 x2 = (int)((-xlocations[l]+xlocations[2*layers-l-1]))-1;
00421 if (x2 > 0)
00422 x1 = xlocations[l]+RANDOM()%x2+1;
00423 else
00424 x1 = xlocations[l]+1;
00425 y1 = (int)ylocations[2*layers-l-1];
00426 break;
00427 }
00428 }
00429 }
00430
00431 if (options&OPT_NO_DOORS)
00432 maze[x1][y1] = '#';
00433 else
00434 maze[x1][y1] = 'D';
00435 }
00436
00437
00438 l = layers-1;
00439 x1 = (int)(xlocations[l]+xlocations[2*layers-l-1])/2;
00440 y1 = (int)(ylocations[l]+ylocations[2*layers-l-1])/2;
00441 maze[x1][y1] = 'C';
00442
00443
00444 free(xlocations);
00445 free(ylocations);
00446 }
00447
00460 void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
00461 int i, maxlayers;
00462 float *xlocations;
00463 float *ylocations;
00464
00465 maxlayers = (MIN(xsize, ysize)-2)/5;
00466 if (!maxlayers)
00467 return;
00468 if (layers > maxlayers)
00469 layers = maxlayers;
00470 if (layers == 0)
00471 layers = (RANDOM()%maxlayers)+1;
00472 xlocations = (float *)calloc(sizeof(float), 2*layers);
00473 ylocations = (float *)calloc(sizeof(float), 2*layers);
00474
00475
00476 if (option&OPT_IRR_SPACE) {
00477 int x_spaces_available, y_spaces_available;
00478
00479 x_spaces_available = (xsize-2)-3*layers+1;
00480 y_spaces_available = (ysize-2)-3*layers+1;
00481
00482
00483 for (i = 0; i < 2*layers; i++) {
00484 float xpitch = 2, ypitch = 2;
00485
00486 if (x_spaces_available > 0)
00487 xpitch = 2
00488 +(RANDOM()%x_spaces_available
00489 +RANDOM()%x_spaces_available
00490 +RANDOM()%x_spaces_available)/3;
00491
00492 if (y_spaces_available > 0)
00493 ypitch = 2
00494 +(RANDOM()%y_spaces_available
00495 +RANDOM()%y_spaces_available
00496 +RANDOM()%y_spaces_available)/3;
00497 if (i < layers)
00498 xlocations[i] = ((i > 0) ? xlocations[i-1] : 0)+xpitch;
00499 else
00500 xlocations[i] = xsize-1;
00501
00502 if (i < layers)
00503 ylocations[i] = ((i > 0) ? ylocations[i-1] : 0)+ypitch;
00504 else
00505 ylocations[i] = ysize-1;
00506 x_spaces_available -= xpitch-2;
00507 y_spaces_available -= ypitch-2;
00508 }
00509
00510 }
00511
00512 if (!(option&OPT_IRR_SPACE)) {
00513 float xpitch, ypitch;
00514
00515 xpitch = (xsize-2.0)/(2.0*layers+1);
00516 ypitch = (ysize-2.0)/(layers+1);
00517 xlocations[0] = xpitch;
00518 ylocations[0] = ypitch;
00519 for (i = 1; i < 2*layers; i++) {
00520 if (i < layers)
00521 xlocations[i] = xlocations[i-1]+xpitch;
00522 else
00523 xlocations[i] = xsize-1;
00524 if (i < layers)
00525 ylocations[i] = ylocations[i-1]+ypitch;
00526 else
00527 ylocations[i] = ysize-1;
00528 }
00529 }
00530
00531
00532 draw_onion(maze, xlocations, ylocations, layers);
00533 make_doors(maze, xlocations, ylocations, layers, option);
00534 }