|
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 00030 #include <global.h> 00031 00043 void find_in_layout(int mode, char target, int *fx, int *fy, char **layout, RMParms *RP) 00044 { 00045 int M, x, y; 00046 00047 *fx = -1; 00048 *fy = -1; 00049 00050 /* if a starting point isn't given, pick one */ 00051 if (mode < 1 || mode > 4) 00052 { 00053 M = RANDOM() % 4 + 1; 00054 } 00055 else 00056 { 00057 M = mode; 00058 } 00059 00060 /* four different search starting points and methods so that 00061 we can do something different for symmetrical maps instead of 00062 the same damned thing every time. */ 00063 switch (M) 00064 { 00065 /* Search from top left down/right */ 00066 case 1: 00067 { 00068 for (x = 1; x < RP->Xsize; x++) 00069 { 00070 for (y = 1; y < RP->Ysize; y++) 00071 { 00072 if (layout[x][y] == target) 00073 { 00074 *fx = x; 00075 *fy = y; 00076 00077 return; 00078 } 00079 } 00080 } 00081 00082 break; 00083 } 00084 00085 /* Search from top right down/left */ 00086 case 2: 00087 { 00088 for (x = RP->Xsize - 2; x > 0; x--) 00089 { 00090 for (y = 1; y < RP->Ysize - 1; y++) 00091 { 00092 if (layout[x][y] == target) 00093 { 00094 *fx = x; 00095 *fy = y; 00096 00097 return; 00098 } 00099 } 00100 } 00101 00102 break; 00103 } 00104 00105 /* Search from bottom-left up-right */ 00106 case 3: 00107 { 00108 for (x = 1; x < RP->Xsize - 1; x++) 00109 { 00110 for (y = RP->Ysize - 2; y > 0; y--) 00111 { 00112 if (layout[x][y] == target) 00113 { 00114 *fx = x; 00115 *fy = y; 00116 00117 return; 00118 } 00119 } 00120 } 00121 00122 break; 00123 } 00124 00125 /* Search from bottom-right up-left */ 00126 case 4: 00127 { 00128 for (x = RP->Xsize - 2; x > 0; x--) 00129 { 00130 for (y = RP->Ysize - 2; y > 0; y--) 00131 { 00132 if (layout[x][y] == target) 00133 { 00134 *fx = x; 00135 *fy = y; 00136 00137 return; 00138 } 00139 } 00140 } 00141 00142 break; 00143 } 00144 } 00145 } 00146 00159 void place_exits(mapstruct *map, char **maze, char *exitstyle, int orientation, RMParms *RP) 00160 { 00161 mapstruct *style_map_down = NULL, *style_map_up = NULL; 00162 object *the_exit_down; 00163 object *the_exit_up; 00164 /* magic mouth saying this is a random map. */ 00165 object *random_sign; 00166 int cx = -1, cy = -1; 00167 int upx = -1, upy = -1; 00168 int downx = -1, downy = -1, j; 00169 00170 if (orientation == 0) 00171 { 00172 orientation = RANDOM() % 6 + 1; 00173 } 00174 00175 switch (orientation) 00176 { 00177 case 1: 00178 style_map_up = find_style("/styles/exitstyles/up", exitstyle, -1); 00179 style_map_down = find_style("/styles/exitstyles/down", exitstyle, -1); 00180 00181 break; 00182 00183 case 2: 00184 style_map_up = find_style("/styles/exitstyles/down", exitstyle, -1); 00185 style_map_down = find_style("/styles/exitstyles/up", exitstyle, -1); 00186 00187 break; 00188 00189 default: 00190 style_map_up = find_style("/styles/exitstyles/generic", exitstyle, -1); 00191 style_map_down = style_map_up; 00192 00193 break; 00194 } 00195 00196 if (style_map_up == NULL) 00197 { 00198 the_exit_up = arch_to_object(find_archetype("exit")); 00199 } 00200 else 00201 { 00202 object *tmp = pick_random_object(style_map_up); 00203 the_exit_up = arch_to_object(tmp->arch); 00204 } 00205 00206 /* we need a down exit only if we're recursing. */ 00207 if (RP->dungeon_level < RP->dungeon_depth || RP->final_map[0] != 0) 00208 { 00209 if (style_map_down == NULL) 00210 { 00211 the_exit_down = arch_to_object(find_archetype("exit")); 00212 } 00213 else 00214 { 00215 object *tmp = pick_random_object(style_map_down); 00216 the_exit_down = arch_to_object(tmp->arch); 00217 } 00218 } 00219 else 00220 { 00221 the_exit_down = NULL; 00222 } 00223 00224 /* Set up the up exit */ 00225 the_exit_up->stats.hp = RP->origin_x; 00226 the_exit_up->stats.sp = RP->origin_y; 00227 FREE_AND_COPY_HASH(the_exit_up->slaying, RP->origin_map); 00228 00229 /* figure out where to put the entrance */ 00230 00231 /* First, look for a '<' char */ 00232 find_in_layout(0, '<', &upx, &upy, maze, RP); 00233 00234 /* next, look for a C, the map center. */ 00235 find_in_layout(0, 'C', &cx, &cy, maze, RP); 00236 00237 /* If we didn't find an up, find an empty place far from the center */ 00238 if (upx == -1 && cx != -1) 00239 { 00240 if (cx > RP->Xsize / 2) 00241 { 00242 upx = 1; 00243 } 00244 else 00245 { 00246 upx = RP->Xsize - 2; 00247 } 00248 00249 if (cy > RP->Ysize / 2) 00250 { 00251 upy = 1; 00252 } 00253 else 00254 { 00255 upy = RP->Ysize - 2; 00256 } 00257 00258 /* find an empty place far from the center */ 00259 if (upx == 1 && upy == 1) 00260 { 00261 find_in_layout(1, 0, &upx, &upy, maze, RP); 00262 } 00263 else if (upx == 1 && upy > 1) 00264 { 00265 find_in_layout(3, 0, &upx, &upy, maze, RP); 00266 } 00267 else if (upx > 1 && upy == 1) 00268 { 00269 find_in_layout(2, 0, &upx, &upy, maze, RP); 00270 } 00271 else if (upx > 1 && upy > 1) 00272 { 00273 find_in_layout(4, 0, &upx, &upy, maze, RP); 00274 } 00275 } 00276 00277 /* No indication of where to place the exit, so just place it. */ 00278 if (upx == -1) 00279 { 00280 find_in_layout(0, 0, &upx, &upy, maze, RP); 00281 } 00282 00283 the_exit_up->x = upx; 00284 the_exit_up->y = upy; 00285 00286 /* Surround the exits with notices that this is a random map. */ 00287 for (j = 1; j < 9; j++) 00288 { 00289 if (!wall_blocked(map, the_exit_up->x + freearr_x[j], the_exit_up->y + freearr_y[j])) 00290 { 00291 char buf[MAX_BUF]; 00292 00293 random_sign = get_archetype("sign"); 00294 random_sign->x = the_exit_up->x + freearr_x[j]; 00295 random_sign->y = the_exit_up->y + freearr_y[j]; 00296 00297 snprintf(buf, sizeof(buf), "This is a random map.\nLevel: %d\n", RP->dungeon_level); 00298 FREE_AND_COPY_HASH(random_sign->msg, buf); 00299 insert_ob_in_map(random_sign, map, NULL, INS_NO_MERGE | INS_NO_WALK_ON); 00300 } 00301 } 00302 00303 /* Block the exit so things don't get dumped on top of it. */ 00304 SET_FLAG(the_exit_up, FLAG_NO_PASS); 00305 insert_ob_in_map(the_exit_up, map, NULL, INS_NO_MERGE | INS_NO_WALK_ON); 00306 maze[the_exit_up->x][the_exit_up->y] = '<'; 00307 00308 /* Set the starting x, y for this map */ 00309 MAP_ENTER_X(map) = the_exit_up->x; 00310 MAP_ENTER_Y(map) = the_exit_up->y; 00311 00312 /* First, look for a '>' character */ 00313 find_in_layout(0, '>', &downx, &downy, maze, RP); 00314 00315 /* If no > is found use C */ 00316 if (downx == -1) 00317 { 00318 downx = cx; 00319 downy = cy; 00320 } 00321 00322 /* make the other exit far away from this one if 00323 * there's no center. */ 00324 if (downx == -1) 00325 { 00326 if (upx > RP->Xsize / 2) 00327 { 00328 downx = 1; 00329 } 00330 else 00331 { 00332 downx = RP->Xsize - 2; 00333 } 00334 00335 if (upy > RP->Ysize / 2) 00336 { 00337 downy = 1; 00338 } 00339 else 00340 { 00341 downy = RP->Ysize - 2; 00342 } 00343 00344 /* find an empty place far from the entrance */ 00345 if (downx == 1 && downy == 1) 00346 { 00347 find_in_layout(1, 0, &downx, &downy, maze, RP); 00348 } 00349 else if (downx == 1 && downy > 1) 00350 { 00351 find_in_layout(3, 0, &downx, &downy, maze, RP); 00352 } 00353 else if (downx > 1 && downy == 1) 00354 { 00355 find_in_layout(2, 0, &downx, &downy, maze, RP); 00356 } 00357 else if (downx > 1 && downy > 1) 00358 { 00359 find_in_layout(4, 0, &downx, &downy, maze, RP); 00360 } 00361 } 00362 00363 /* No indication of where to place the down exit, so just place it */ 00364 if (downx == -1) 00365 { 00366 find_in_layout(0, 0, &downx, &downy, maze, RP); 00367 } 00368 00369 if (the_exit_down) 00370 { 00371 int i = find_first_free_spot(the_exit_down->arch, NULL, map, downx, downy); 00372 00373 the_exit_down->x = downx + freearr_x[i]; 00374 the_exit_down->y = downy + freearr_y[i]; 00375 00376 RP->origin_x = the_exit_down->x; 00377 RP->origin_y = the_exit_down->y; 00378 00379 /* the identifier for making a random map. */ 00380 if (RP->dungeon_level >= RP->dungeon_depth && RP->final_map[0] != '\0') 00381 { 00382 mapstruct *new_map; 00383 object *the_exit_back = arch_to_object(the_exit_up->arch), *tmp; 00384 00385 /* load it */ 00386 if ((new_map = ready_map_name(RP->final_map, MAP_UNIQUE(map) ? 1 : 0)) == NULL) 00387 { 00388 return; 00389 } 00390 00391 FREE_AND_COPY_HASH(the_exit_down->slaying, RP->final_map); 00392 FREE_AND_COPY_HASH(new_map->path, RP->final_map); 00393 the_exit_down->stats.hp = MAP_ENTER_X(new_map); 00394 the_exit_down->stats.sp = MAP_ENTER_Y(new_map); 00395 00396 for (tmp = GET_MAP_OB(new_map, MAP_ENTER_X(new_map), MAP_ENTER_Y(new_map)); tmp; tmp = tmp->above) 00397 { 00398 /* Remove exit back to previous random map. There should only be one 00399 * which is why we break out. To try to process more than one 00400 * would require keeping a 'next' pointer, ad free_object kills tmp, which 00401 * breaks the for loop. */ 00402 if (tmp->type == EXIT) 00403 { 00404 remove_ob(tmp); 00405 break; 00406 } 00407 } 00408 00409 /* Setup the exit back */ 00410 FREE_AND_ADD_REF_HASH(the_exit_back->slaying, map->path); 00411 the_exit_back->stats.hp = the_exit_down->x; 00412 the_exit_back->stats.sp = the_exit_down->y; 00413 the_exit_back->x = MAP_ENTER_X(new_map); 00414 the_exit_back->y = MAP_ENTER_Y(new_map); 00415 00416 insert_ob_in_map(the_exit_back, new_map, NULL, INS_NO_MERGE | INS_NO_WALK_ON); 00417 00418 /* So it gets swapped out */ 00419 set_map_timeout(new_map); 00420 } 00421 else 00422 { 00423 char buf[2048]; 00424 00425 write_map_parameters_to_string(buf, RP); 00426 FREE_AND_COPY_HASH(the_exit_down->msg, buf); 00427 FREE_AND_COPY_HASH(the_exit_down->slaying, "/random/"); 00428 the_exit_down->stats.hp = 0; 00429 the_exit_down->stats.sp = 0; 00430 } 00431 00432 /* Block the exit so things don't get dumped on top of it. */ 00433 SET_FLAG(the_exit_down, FLAG_NO_PASS); 00434 00435 insert_ob_in_map(the_exit_down, map, NULL, INS_NO_MERGE | INS_NO_WALK_ON); 00436 00437 maze[the_exit_down->x][the_exit_down->y] = '>'; 00438 } 00439 } 00440 00447 void unblock_exits(mapstruct *map, char **maze, RMParms *RP) 00448 { 00449 int x, y; 00450 object *walk; 00451 00452 for (x = 0; x < RP->Xsize; x++) 00453 { 00454 for (y = 0; y < RP->Ysize; y++) 00455 { 00456 if (maze[x][y] == '>' || maze[x][y] == '<') 00457 { 00458 for (walk = get_map_ob(map, x, y); walk != NULL; walk = walk->above) 00459 { 00460 if (QUERY_FLAG(walk, FLAG_NO_PASS) && walk->type != DOOR) 00461 { 00462 CLEAR_FLAG(walk, FLAG_NO_PASS); 00463 update_object(walk, UP_OBJ_FLAGS); 00464 } 00465 } 00466 } 00467 } 00468 } 00469 }
1.7.4