|
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 00052 #include <global.h> 00053 00054 void centered_onion(char **maze, int xsize, int ysize, int option, int layers); 00055 void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers); 00056 void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers); 00057 void draw_onion(char **maze, float *xlocations, float *ylocations, int layers); 00058 void make_doors(char **maze, float *xlocations, float *ylocations, int layers, int options); 00059 00067 char **map_gen_onion(int xsize, int ysize, int option, int layers) 00068 { 00069 int i, j; 00070 00071 /* Allocate that array, set it up */ 00072 char **maze = (char **) calloc(sizeof(char *), xsize); 00073 00074 for (i = 0; i < xsize; i++) 00075 { 00076 maze[i] = (char *) calloc(sizeof(char), ysize); 00077 } 00078 00079 /* Pick some random options if option = 0 */ 00080 if (option == 0) 00081 { 00082 switch (RANDOM() % 3) 00083 { 00084 case 0: 00085 option |= OPT_CENTERED; 00086 break; 00087 00088 case 1: 00089 option |= OPT_BOTTOM_C; 00090 break; 00091 00092 case 2: 00093 option |= OPT_BOTTOM_R; 00094 break; 00095 } 00096 00097 if (RANDOM() % 2) 00098 { 00099 option |= OPT_LINEAR; 00100 } 00101 00102 if (RANDOM() % 2) 00103 { 00104 option |=OPT_IRR_SPACE; 00105 } 00106 } 00107 00108 /* Write the outer walls, if appropriate. */ 00109 if (!(option & OPT_WALL_OFF)) 00110 { 00111 for (i = 0; i < xsize; i++) 00112 { 00113 maze[i][0] = maze[i][ysize - 1] = '#'; 00114 } 00115 00116 for (j = 0; j < ysize; j++) 00117 { 00118 maze[0][j] = maze[xsize - 1][j] = '#'; 00119 } 00120 } 00121 00122 if (option & OPT_WALLS_ONLY) 00123 { 00124 return maze; 00125 } 00126 00127 /* pick off the mutually exclusive options */ 00128 if (option & OPT_BOTTOM_R) 00129 { 00130 bottom_right_centered_onion(maze, xsize, ysize, option, layers); 00131 } 00132 else if (option & OPT_BOTTOM_C) 00133 { 00134 bottom_centered_onion(maze, xsize, ysize, option, layers); 00135 } 00136 else if (option & OPT_CENTERED) 00137 { 00138 centered_onion(maze, xsize, ysize, option, layers); 00139 } 00140 00141 return maze; 00142 } 00143 00151 void centered_onion(char **maze, int xsize, int ysize, int option, int layers) 00152 { 00153 int i, maxlayers; 00154 float *xlocations, *ylocations; 00155 00156 maxlayers = (MIN(xsize, ysize) - 2) / 5; 00157 00158 /* map too small to onionize */ 00159 if (!maxlayers) 00160 { 00161 return; 00162 } 00163 00164 if (layers > maxlayers) 00165 { 00166 layers = maxlayers; 00167 } 00168 00169 if (layers == 0) 00170 { 00171 layers = (RANDOM() % maxlayers) + 1; 00172 } 00173 00174 xlocations = (float *) calloc(sizeof(float), 2 * layers); 00175 ylocations = (float *) calloc(sizeof(float), 2 * layers); 00176 00177 /* Place all the walls */ 00178 00179 /* Randomly spaced */ 00180 if (option & OPT_IRR_SPACE) 00181 { 00182 int x_spaces_available, y_spaces_available; 00183 00184 /* the "extra" spaces available for spacing between layers */ 00185 x_spaces_available = (xsize - 2) - 6 * layers + 1; 00186 y_spaces_available = (ysize - 2) - 6 * layers + 1; 00187 00188 /* Pick an initial random pitch */ 00189 for (i = 0; i < 2 * layers; i++) 00190 { 00191 float xpitch = 2, ypitch = 2; 00192 00193 if (x_spaces_available > 0) 00194 { 00195 xpitch = 2.0f + (float) (RANDOM() % x_spaces_available + RANDOM() % x_spaces_available + RANDOM() % x_spaces_available) / 3.0f; 00196 } 00197 00198 if (y_spaces_available>0) 00199 { 00200 ypitch = 2.0f + (float) (RANDOM() % y_spaces_available + RANDOM() % y_spaces_available + RANDOM() % y_spaces_available) / 3.0f; 00201 } 00202 00203 xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch; 00204 ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch; 00205 00206 x_spaces_available -= (int) xpitch - 2; 00207 y_spaces_available -= (int) ypitch - 2; 00208 } 00209 } 00210 00211 /* evenly spaced */ 00212 if (!(option & OPT_IRR_SPACE)) 00213 { 00214 /* pitch of the onion layers */ 00215 float xpitch, ypitch; 00216 00217 xpitch = (float) (xsize - 2) / (2.0f * (float) (layers + 1)); 00218 ypitch = (float) (ysize - 2) / (2.0f * (float) (layers + 1)); 00219 00220 xlocations[0] = xpitch; 00221 ylocations[0] = ypitch; 00222 00223 for (i = 1; i < 2 * layers; i++) 00224 { 00225 xlocations[i] = xlocations[i - 1] + xpitch; 00226 ylocations[i] = ylocations[i - 1] + ypitch; 00227 } 00228 } 00229 00230 /* draw all the onion boxes. */ 00231 draw_onion(maze, xlocations, ylocations, layers); 00232 make_doors(maze, xlocations, ylocations, layers, option); 00233 } 00234 00242 void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers) 00243 { 00244 int i, maxlayers; 00245 float *xlocations, *ylocations; 00246 00247 maxlayers = (MIN(xsize, ysize) - 2) / 5; 00248 00249 /* map too small to onionize */ 00250 if (!maxlayers) 00251 { 00252 return; 00253 } 00254 00255 if (layers > maxlayers) 00256 { 00257 layers = maxlayers; 00258 } 00259 00260 if (layers == 0) 00261 { 00262 layers = (RANDOM() % maxlayers) + 1; 00263 } 00264 00265 xlocations = (float *) calloc(sizeof(float), 2 * layers); 00266 ylocations = (float *) calloc(sizeof(float), 2 * layers); 00267 00268 /* place all the walls */ 00269 00270 /* randomly spaced */ 00271 if (option & OPT_IRR_SPACE) 00272 { 00273 int x_spaces_available, y_spaces_available; 00274 00275 /* the "extra" spaces available for spacing between layers */ 00276 x_spaces_available = (xsize - 2) - 6 * layers + 1; 00277 y_spaces_available = (ysize - 2) - 3 * layers + 1; 00278 00279 /* Pick an initial random pitch */ 00280 for (i = 0; i < 2 * layers; i++) 00281 { 00282 float xpitch = 2, ypitch = 2; 00283 00284 if (x_spaces_available > 0) 00285 { 00286 xpitch = 2.0f + (float) (RANDOM() % x_spaces_available + RANDOM() % x_spaces_available + RANDOM() % x_spaces_available) / 3.0f; 00287 } 00288 00289 if (y_spaces_available > 0) 00290 { 00291 ypitch = 2.0f + (float) (RANDOM() % y_spaces_available + RANDOM() % y_spaces_available + RANDOM() % y_spaces_available) / 3.0f; 00292 } 00293 00294 xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch; 00295 00296 if (i < layers) 00297 { 00298 ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch; 00299 } 00300 else 00301 { 00302 ylocations[i] = (float) (ysize - 1); 00303 } 00304 00305 x_spaces_available -= (int) xpitch - 2; 00306 y_spaces_available -= (int) ypitch - 2; 00307 } 00308 } 00309 00310 /* evenly spaced */ 00311 if (!(option & OPT_IRR_SPACE)) 00312 { 00313 /* pitch of the onion layers */ 00314 float xpitch, ypitch; 00315 00316 xpitch = (float) (xsize - 2) / (2.0f * (float) (layers + 1)); 00317 ypitch = (float) (ysize - 2) / (float) (layers + 1); 00318 00319 xlocations[0] = xpitch; 00320 ylocations[0] = ypitch; 00321 00322 for (i = 1; i < 2 * layers; i++) 00323 { 00324 xlocations[i] = xlocations[i - 1] + xpitch; 00325 00326 if (i < layers) 00327 { 00328 ylocations[i] = ylocations[i - 1] + ypitch; 00329 } 00330 else 00331 { 00332 ylocations[i] = (float) (ysize - 1); 00333 } 00334 } 00335 } 00336 00337 /* draw all the onion boxes. */ 00338 draw_onion(maze, xlocations, ylocations, layers); 00339 make_doors(maze, xlocations, ylocations, layers, option); 00340 } 00341 00348 void draw_onion(char **maze, float *xlocations, float *ylocations, int layers) 00349 { 00350 int i, j, l; 00351 00352 for (l = 0; l < layers; l++) 00353 { 00354 int x1, x2, y1, y2; 00355 00356 /* horizontal segments */ 00357 y1 = (int) ylocations[l]; 00358 y2 = (int) ylocations[2 * layers - l - 1]; 00359 00360 for (i = (int) xlocations[l]; i <= (int) xlocations[2 * layers - l - 1]; i++) 00361 { 00362 maze[i][y1] = '#'; 00363 maze[i][y2] = '#'; 00364 } 00365 00366 /* vertical segments */ 00367 x1 = (int) xlocations[l]; 00368 x2 = (int) xlocations[2 * layers - l - 1]; 00369 00370 for (j = (int) ylocations[l]; j <= (int) ylocations[2 * layers - l - 1]; j++) 00371 { 00372 maze[x1][j] = '#'; 00373 maze[x2][j] = '#'; 00374 } 00375 } 00376 } 00377 00385 void make_doors(char **maze, float *xlocations, float *ylocations, int layers, int options) 00386 { 00387 /* number of different walls on which we could place a door */ 00388 int freedoms; 00389 /* left, 1, top, 2, right, 3, bottom 4 */ 00390 int which_wall; 00391 int l, x1 = 0, x2, y1 = 0, y2; 00392 00393 /* centered */ 00394 freedoms = 4; 00395 00396 if (options & OPT_BOTTOM_C) 00397 { 00398 freedoms = 3; 00399 } 00400 00401 if (options & OPT_BOTTOM_R) 00402 { 00403 freedoms = 2; 00404 } 00405 00406 if (layers <= 0) 00407 { 00408 return; 00409 } 00410 00411 /* Pick which wall will have a door. */ 00412 which_wall = RANDOM() % freedoms + 1; 00413 00414 for (l = 0; l < layers; l++) 00415 { 00416 /* linear door placement. */ 00417 if (options & OPT_LINEAR) 00418 { 00419 switch (which_wall) 00420 { 00421 /* Left hand wall */ 00422 case 1: 00423 x1 = (int) xlocations[l]; 00424 y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2); 00425 00426 break; 00427 00428 /* Top wall placement */ 00429 case 2: 00430 x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2); 00431 y1 = (int) ylocations[l]; 00432 00433 break; 00434 00435 /* Right wall placement */ 00436 case 3: 00437 x1 = (int) xlocations[2 * layers - l - 1]; 00438 y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2); 00439 00440 break; 00441 00442 /* Bottom wall placement */ 00443 case 4: 00444 x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2); 00445 y1 = (int) ylocations[2 * layers - l - 1]; 00446 00447 break; 00448 } 00449 } 00450 /* random door placement. */ 00451 else 00452 { 00453 which_wall = RANDOM() % freedoms + 1; 00454 00455 switch (which_wall) 00456 { 00457 /* Left hand wall */ 00458 case 1: 00459 x1 = (int) xlocations[l]; 00460 y2 = (int) (ylocations[2 * layers - l - 1] - ylocations[l] - 1.0f); 00461 00462 if (y2 > 0) 00463 { 00464 y1 = (int) ylocations[l] + RANDOM() % y2 + 1; 00465 } 00466 else 00467 { 00468 y1 = (int) ylocations[l] + 1; 00469 } 00470 00471 break; 00472 00473 /* Top wall placement */ 00474 case 2: 00475 x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; 00476 00477 if (x2 > 0) 00478 { 00479 x1 = (int) xlocations[l] + RANDOM() % x2 + 1; 00480 } 00481 else 00482 { 00483 x1 = (int) xlocations[l] + 1; 00484 } 00485 00486 y1 = (int) ylocations[l]; 00487 00488 break; 00489 00490 /* Right wall placement */ 00491 case 3: 00492 x1 = (int) xlocations[2 * layers - l - 1]; 00493 y2 = (int) ((-ylocations[l] + ylocations[2 * layers - l - 1])) - 1; 00494 00495 if (y2 > 0) 00496 { 00497 y1 = (int) ylocations[l] + RANDOM() % y2 + 1; 00498 } 00499 else 00500 { 00501 y1 = (int) ylocations[l] + 1; 00502 } 00503 00504 break; 00505 00506 /* Bottom wall placement */ 00507 case 4: 00508 x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1; 00509 00510 if (x2 > 0) 00511 { 00512 x1 = (int) xlocations[l] + RANDOM() % x2 + 1; 00513 } 00514 else 00515 { 00516 x1 = (int) xlocations[l] + 1; 00517 } 00518 00519 y1 = (int) ylocations[2 * layers - l - 1]; 00520 00521 break; 00522 } 00523 } 00524 00525 if (options & OPT_NO_DOORS) 00526 { 00527 /* no door. */ 00528 maze[x1][y1] = '#'; 00529 } 00530 else 00531 { 00532 /* write the door */ 00533 maze[x1][y1] = 'D'; 00534 } 00535 } 00536 00537 /* mark the center of the maze with a C */ 00538 l = layers - 1; 00539 x1 = (int) (xlocations[l] + xlocations[2 * layers - l - 1]) / 2; 00540 y1 = (int) (ylocations[l] + ylocations[2 * layers - l - 1]) / 2; 00541 00542 maze[x1][y1] = 'C'; 00543 00544 /* Not needed anymore */ 00545 free(xlocations); 00546 free(ylocations); 00547 } 00548 00556 void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers) 00557 { 00558 int i, maxlayers; 00559 float *xlocations, *ylocations; 00560 00561 maxlayers = (MIN(xsize, ysize) - 2) / 5; 00562 00563 /* map too small to onionize */ 00564 if (!maxlayers) 00565 { 00566 return; 00567 } 00568 00569 if (layers > maxlayers) 00570 { 00571 layers = maxlayers; 00572 } 00573 00574 if (layers == 0) 00575 { 00576 layers = (RANDOM() % maxlayers)+1; 00577 } 00578 00579 xlocations = (float *) calloc(sizeof(float), 2 * layers); 00580 ylocations = (float *) calloc(sizeof(float), 2 * layers); 00581 00582 /* place all the walls */ 00583 00584 /* randomly spaced */ 00585 if (option & OPT_IRR_SPACE) 00586 { 00587 int x_spaces_available, y_spaces_available; 00588 00589 /* the "extra" spaces available for spacing between layers */ 00590 x_spaces_available = (xsize - 2) - 3 * layers + 1; 00591 y_spaces_available = (ysize - 2) - 3 * layers + 1; 00592 00593 /* Pick an initial random pitch */ 00594 for (i = 0; i < 2 * layers; i++) 00595 { 00596 float xpitch = 2, ypitch = 2; 00597 00598 if (x_spaces_available>0) 00599 { 00600 xpitch = 2.0f + (float) (RANDOM() % x_spaces_available + RANDOM() % x_spaces_available + RANDOM() % x_spaces_available) / 3.0f; 00601 } 00602 00603 if (y_spaces_available > 0) 00604 { 00605 ypitch = 2.0f + (float) (RANDOM() % y_spaces_available + RANDOM() % y_spaces_available + RANDOM() % y_spaces_available) / 3.0f; 00606 } 00607 00608 if (i < layers) 00609 { 00610 xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch; 00611 } 00612 else 00613 { 00614 xlocations[i] = (float) (xsize - 1); 00615 } 00616 00617 if (i < layers) 00618 { 00619 ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch; 00620 } 00621 else 00622 { 00623 ylocations[i] = (float) (ysize - 1); 00624 } 00625 00626 x_spaces_available -= (int) xpitch - 2; 00627 y_spaces_available -= (int) ypitch - 2; 00628 } 00629 00630 } 00631 00632 /* evenly spaced */ 00633 if (!(option & OPT_IRR_SPACE)) 00634 { 00635 /* pitch of the onion layers */ 00636 float xpitch, ypitch; 00637 00638 xpitch = (float) (xsize - 2) / (float) (2 * layers + 1); 00639 ypitch = (float) (ysize - 2) / (float) (layers + 1); 00640 00641 xlocations[0] = xpitch; 00642 ylocations[0] = ypitch; 00643 00644 for (i = 1; i < 2 * layers; i++) 00645 { 00646 if (i < layers) 00647 { 00648 xlocations[i] = xlocations[i - 1] + xpitch; 00649 } 00650 else 00651 { 00652 xlocations[i] = (float) (xsize - 1); 00653 } 00654 00655 if (i < layers) 00656 { 00657 ylocations[i] = ylocations[i - 1] + ypitch; 00658 } 00659 else 00660 { 00661 ylocations[i] = (float) (ysize - 1); 00662 } 00663 } 00664 } 00665 00666 /* draw all the onion boxes. */ 00667 draw_onion(maze, xlocations, ylocations, layers); 00668 make_doors(maze, xlocations, ylocations, layers, option); 00669 }
1.7.4