Crossfire Server, Branch 1.12  R12190
expand2x.c
Go to the documentation of this file.
00001 /*
00002  * --------------------------------------------------------------------------
00003  * $Id: expand2x.c 11578 2009-02-23 22:02:27Z lalo $
00004  *
00005  * ALGORITHM
00006  *
00007  * ... (TBW)
00008  */
00009 
00017 #include <stdlib.h>   /* just in case */
00018 #include <expand2x.h>   /* use compiler to do sanity check */
00019 
00020 
00021 /* PROTOTYPES */
00022 
00023 static void expand_misc(char **newlayout, int i, int j, char **layout);
00024 static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize);
00025 static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize);
00026 
00027 /* FUNCTIONS */
00028 
00039 char **expand2x(char **layout, int xsize, int ysize) {
00040     int i, j;
00041     int nxsize = xsize*2-1;
00042     int nysize = ysize*2-1;
00043 
00044     /* Allocate new layout */
00045     char **newlayout = (char **)calloc(sizeof(char *), nxsize);
00046     for (i = 0; i < nxsize; i++) {
00047         newlayout[i] = (char *)calloc(sizeof(char), nysize);
00048     }
00049 
00050     for (i = 0; i < xsize; i++) {
00051         for (j = 0; j < ysize; j++) {
00052             switch (layout[i][j]) {
00053             case '#':
00054                 expand_wall(newlayout, i, j, layout, xsize, ysize);
00055                 break;
00056 
00057             case 'D':
00058                 expand_door(newlayout, i, j, layout, xsize, ysize);
00059                 break;
00060 
00061             default:
00062                 expand_misc(newlayout, i, j, layout);
00063             }
00064         }
00065     }
00066 
00067     /* Dump old layout */
00068     for (i = 0; i < xsize; i++) {
00069         free(layout[i]);
00070     }
00071     free(layout);
00072 
00073     return newlayout;
00074 }
00075 
00089 static void expand_misc(char **newlayout, int i, int j, char **layout) {
00090     newlayout[i*2][j*2] = layout[i][j];
00091     /* (Note: no need to reset rest of 2x2 area to \0 because calloc does that
00092      * for us.) */
00093 }
00094 
00115 static int calc_pattern(char ch, char **layout, int i, int j, int xsize, int ysize) {
00116     int pattern = 0;
00117 
00118     if (i+1 < xsize && layout[i+1][j] == ch)
00119         pattern |= 1;
00120 
00121     if (j+1 < ysize) {
00122         if (layout[i][j+1] == ch)
00123             pattern |= 2;
00124         if (i+1 < xsize && layout[i+1][j+1] == ch)
00125             pattern |= 4;
00126     }
00127 
00128     return pattern;
00129 }
00130 
00146 static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize) {
00147     int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
00148     int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
00149     int both_pattern = wall_pattern|door_pattern;
00150 
00151     newlayout[i*2][j*2] = '#';
00152     if (i+1 < xsize) {
00153         if (both_pattern&1) {
00154             /* join walls/doors to the right */
00155             newlayout[i*2+1][j*2] = layout[i+1][j];
00156         }
00157     }
00158 
00159     if (j+1 < ysize) {
00160         if (both_pattern&2) {
00161             /* join walls/doors to the bottom */
00162             newlayout[i*2][j*2+1] = layout[i][j+1];
00163         }
00164 
00165         if (wall_pattern == 7) {
00166             /* if orig layout is a 2x2 wall block,
00167              * we fill the result with walls. */
00168             newlayout[i*2+1][j*2+1] = '#';
00169         }
00170     }
00171 }
00172 
00188 static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize) {
00189     int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
00190     int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
00191     int join_pattern;
00192 
00193     /* Doors "like" to connect to walls more than other doors. If there is
00194      * a wall and another door, this door will connect to the wall and
00195      * disconnect from the other door. */
00196     if (wall_pattern&3) {
00197         join_pattern = wall_pattern;
00198     } else {
00199         join_pattern = door_pattern;
00200     }
00201 
00202     newlayout[i*2][j*2] = 'D';
00203     if (i+1 < xsize) {
00204         if (join_pattern&1) {
00205             /* there is a door/wall to the right */
00206             newlayout[i*2+1][j*2] = 'D';
00207         }
00208     }
00209 
00210     if (j+1 < ysize) {
00211         if (join_pattern&2) {
00212             /* there is a door/wall below */
00213             newlayout[i*2][j*2+1] = 'D';
00214         }
00215     }
00216 }