Crossfire Server, Branch 1.12  R12190
wall.c
Go to the documentation of this file.
00001 /*
00002  * static char *rcsid_wall_c =
00003  *   "$Id: wall.c 11578 2009-02-23 22:02:27Z lalo $";
00004  */
00005 
00006 /*
00007     CrossFire, A Multiplayer game for X-windows
00008 
00009     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
00010     Copyright (C) 1992 Frank Tore Johansen
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00025 
00026     The authors can be reached via e-mail at crossfire-devel@real-time.com
00027 */
00028 
00034 #include <global.h>
00035 #include <random_map.h>
00036 #include <rproto.h>
00037 
00056 int surround_flag(char **layout, int i, int j, RMParms *RP) {
00057     int surround_index = 0;
00058 
00059     if ((i > 0) && layout[i-1][j] != 0)
00060         surround_index |= 1;
00061     if ((i < RP->Xsize-1) && layout[i+1][j] != 0)
00062         surround_index |= 2;
00063     if ((j > 0) && layout[i][j-1] != 0)
00064             surround_index |= 4;
00065     if ((j < RP->Ysize-1) && layout[i][j+1] != 0)
00066             surround_index |= 8;
00067     return surround_index;
00068 }
00069 
00088 int surround_flag2(char **layout, int i, int j, RMParms *RP) {
00089     int surround_index = 0;
00090 
00091     if ((i > 0) && layout[i-1][j] == '#')
00092         surround_index |= 1;
00093     if ((i < RP->Xsize-1) && layout[i+1][j] == '#')
00094         surround_index |= 2;
00095     if ((j > 0) && layout[i][j-1] == '#')
00096         surround_index |= 4;
00097     if ((j < RP->Ysize-1) && layout[i][j+1] == '#')
00098         surround_index |= 8;
00099     return surround_index;
00100 }
00101 
00120 int surround_flag3(mapstruct *map, int i, int j, RMParms *RP) {
00121     int surround_index = 0;
00122 
00123     if ((i > 0) && (GET_MAP_MOVE_BLOCK(map, i-1, j)&~MOVE_BLOCK_DEFAULT))
00124         surround_index |= 1;
00125     if ((i < RP->Xsize-1) && (GET_MAP_MOVE_BLOCK(map, i+1, j)&~MOVE_BLOCK_DEFAULT))
00126         surround_index |= 2;
00127     if ((j > 0) && (GET_MAP_MOVE_BLOCK(map, i, j-1)&~MOVE_BLOCK_DEFAULT))
00128         surround_index |= 4;
00129     if ((j < RP->Ysize-1) && (GET_MAP_MOVE_BLOCK(map, i, j+1)&~MOVE_BLOCK_DEFAULT))
00130         surround_index |= 8;
00131 
00132     return surround_index;
00133 }
00134 
00153 int surround_flag4(mapstruct *map, int i, int j, RMParms *RP) {
00154     int surround_index = 0;
00155 
00156     if ((i > 0) && wall_blocked(map, i-1, j))
00157         surround_index |= 1;
00158     if ((i < RP->Xsize-1) && wall_blocked(map, i+1, j))
00159         surround_index |= 2;
00160     if ((j > 0) && wall_blocked(map, i, j-1))
00161         surround_index |= 4;
00162     if ((j < RP->Ysize-1) && wall_blocked(map, i, j+1))
00163         surround_index |= 8;
00164 
00165     return surround_index;
00166 }
00167 
00180 void make_map_walls(mapstruct *map, char **layout, char *w_style, RMParms *RP) {
00181     char styledirname[256];
00182     char stylefilepath[256];
00183     mapstruct *style_map = NULL;
00184     object *the_wall;
00185 
00186     /* get the style map */
00187     if (!strcmp(w_style, "none"))
00188         return;
00189     snprintf(styledirname, sizeof(styledirname), "%s", "/styles/wallstyles");
00190     snprintf(stylefilepath, sizeof(stylefilepath), "%s/%s", styledirname, w_style);
00191     style_map = find_style(styledirname, w_style, -1);
00192     if (style_map == NULL)
00193         return;
00194 
00195     /* fill up the map with the given floor style */
00196     if ((the_wall = pick_random_object(style_map)) != NULL) {
00197         int i, j;
00198         char *cp;
00199         int joinedwalls = 0;
00200         object *thiswall;
00201 
00202         snprintf(RP->wall_name, sizeof(RP->wall_name), "%s", the_wall->arch->name);
00203         if ((cp = strchr(RP->wall_name, '_')) != NULL) {
00204             *cp = 0;
00205             joinedwalls = 1;
00206         }
00207 
00208         for (i = 0; i < RP->Xsize; i++)
00209             for (j = 0; j < RP->Ysize; j++) {
00210                 if (layout[i][j] == '#') {
00211                     if (joinedwalls)
00212                         thiswall = pick_joined_wall(the_wall, layout, i, j, RP);
00213                     else
00214                         thiswall = arch_to_object(the_wall->arch);
00215                     thiswall->x = i;
00216                     thiswall->y = j;
00217                     thiswall->move_block = MOVE_ALL;
00218                     thiswall->move_allow = 0;
00219                     insert_ob_in_map(thiswall, map, thiswall, INS_NO_MERGE|INS_NO_WALK_ON);
00220                 }
00221             }
00222     }
00223 }
00224 
00241 object *pick_joined_wall(object *the_wall, char **layout, int i, int j, RMParms *RP) {
00242     /* 1 = wall to left,
00243        2 = wall to right,
00244        4 = wall above
00245        8 = wall below */
00246     int surround_index = 0;
00247     int l;
00248     char wall_name[64];
00249     archetype *wall_arch = NULL;
00250 
00251     strncpy(wall_name, the_wall->arch->name, sizeof(wall_name));
00252 
00253     /* conventionally, walls are named like this:
00254      wallname_wallcode, where wallcode indicates
00255      a joinedness, and wallname is the wall.
00256      this code depends on the convention for
00257      finding the right wall. */
00258 
00259     /* extract the wall name, which is the text up to the leading _ */
00260     for (l = 0; l < 64; l++) {
00261         if (wall_name[l] == '_') {
00262             wall_name[l] = 0;
00263             break;
00264         }
00265     }
00266 
00267     surround_index = surround_flag2(layout, i, j, RP);
00268 
00269     switch (surround_index) {
00270     case 0:
00271         strcat(wall_name, "_0");
00272         break;
00273 
00274     case 1:
00275         strcat(wall_name, "_1_3");
00276         break;
00277 
00278     case 2:
00279         strcat(wall_name, "_1_4");
00280         break;
00281 
00282     case 3:
00283         strcat(wall_name, "_2_1_2");
00284         break;
00285 
00286     case 4:
00287         strcat(wall_name, "_1_2");
00288         break;
00289 
00290     case 5:
00291         strcat(wall_name, "_2_2_4");
00292         break;
00293 
00294     case 6:
00295         strcat(wall_name, "_2_2_1");
00296         break;
00297 
00298     case 7:
00299         strcat(wall_name, "_3_1");
00300         break;
00301 
00302     case 8:
00303         strcat(wall_name, "_1_1");
00304         break;
00305 
00306     case 9:
00307         strcat(wall_name, "_2_2_3");
00308         break;
00309 
00310     case 10:
00311         strcat(wall_name, "_2_2_2");
00312         break;
00313 
00314     case 11:
00315         strcat(wall_name, "_3_3");
00316         break;
00317 
00318     case 12:
00319         strcat(wall_name, "_2_1_1");
00320         break;
00321 
00322     case 13:
00323         strcat(wall_name, "_3_4");
00324         break;
00325 
00326     case 14:
00327         strcat(wall_name, "_3_2");
00328         break;
00329 
00330     case 15:
00331         strcat(wall_name, "_4");
00332         break;
00333     }
00334     wall_arch = try_find_archetype(wall_name);
00335     if (wall_arch)
00336         return arch_to_object(wall_arch);
00337     else {
00338         return arch_to_object(the_wall->arch);
00339     }
00340 }
00341 
00362 object *retrofit_joined_wall(mapstruct *the_map, int i, int j, int insert_flag, RMParms *RP) {
00363     /* 1 = wall to left,
00364      * 2 = wall to right,
00365      * 4 = wall above
00366      * 8 = wall below
00367      */
00368     int surround_index = 0;
00369     int l;
00370     object *the_wall = NULL;
00371     object *new_wall = NULL;
00372     archetype *wall_arch = NULL;
00373 
00374     /* first find the wall */
00375     for (the_wall = GET_MAP_OB(the_map, i, j); the_wall != NULL; the_wall = the_wall->above)
00376         if ((the_wall->move_type&MOVE_WALK) && the_wall->type != EXIT && the_wall->type != TELEPORTER)
00377             break;
00378 
00379 
00380     /* if what we found is a door, don't remove it, set the_wall to NULL to
00381      * signal that later.
00382      */
00383     if (the_wall && (the_wall->type == DOOR || the_wall->type == LOCKED_DOOR)) {
00384         the_wall = NULL;
00385         /* if we're not supposed to insert a new wall where there wasn't one,
00386          * we've gotta leave.
00387          */
00388         if (insert_flag == 0)
00389             return NULL;
00390     } else if (the_wall == NULL)
00391         return NULL;
00392 
00393     /* canonicalize the wall name */
00394     for (l = 0; l < 64; l++) {
00395         if (RP->wall_name[l] == '_') {
00396             RP->wall_name[l] = 0;
00397             break;
00398         }
00399     }
00400 
00401     surround_index = surround_flag4(the_map, i, j, RP);
00402     /* This would be a lot cleaner to just us a lookup table,
00403      * eg, wall_suffix[surround_index]
00404      */
00405     switch (surround_index) {
00406     case 0:
00407         strcat(RP->wall_name, "_0");
00408         break;
00409 
00410     case 1:
00411         strcat(RP->wall_name, "_1_3");
00412         break;
00413 
00414     case 2:
00415         strcat(RP->wall_name, "_1_4");
00416         break;
00417 
00418     case 3:
00419         strcat(RP->wall_name, "_2_1_2");
00420         break;
00421 
00422     case 4:
00423         strcat(RP->wall_name, "_1_2");
00424         break;
00425 
00426     case 5:
00427         strcat(RP->wall_name, "_2_2_4");
00428         break;
00429 
00430     case 6:
00431         strcat(RP->wall_name, "_2_2_1");
00432         break;
00433 
00434     case 7:
00435         strcat(RP->wall_name, "_3_1");
00436         break;
00437 
00438     case 8:
00439         strcat(RP->wall_name, "_1_1");
00440         break;
00441 
00442     case 9:
00443         strcat(RP->wall_name, "_2_2_3");
00444         break;
00445 
00446     case 10:
00447         strcat(RP->wall_name, "_2_2_2");
00448         break;
00449 
00450     case 11:
00451         strcat(RP->wall_name, "_3_3");
00452         break;
00453 
00454     case 12:
00455         strcat(RP->wall_name, "_2_1_1");
00456         break;
00457 
00458     case 13:
00459         strcat(RP->wall_name, "_3_4");
00460         break;
00461 
00462     case 14:
00463         strcat(RP->wall_name, "_3_2");
00464         break;
00465 
00466     case 15:
00467         strcat(RP->wall_name, "_4");
00468         break;
00469     }
00470     wall_arch = try_find_archetype(RP->wall_name);
00471     if (wall_arch != NULL) {
00472         new_wall = arch_to_object(wall_arch);
00473         new_wall->x = i;
00474         new_wall->y = j;
00475         if (the_wall && the_wall->map) {
00476             remove_ob(the_wall);
00477             free_object(the_wall);
00478         }
00479         the_wall->move_block = MOVE_ALL;
00480         insert_ob_in_map(new_wall, the_map, new_wall, INS_NO_MERGE|INS_NO_WALK_ON);
00481     }
00482     return new_wall;
00483 }