Atrinik Server 2.5
random_maps/expand2x.c
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 
00026 #include <global.h>
00027 
00028 static void expand_misc(char **newlayout, int i, int j, char **layout);
00029 static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize);
00030 static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize);
00031 
00039 char **expand2x(char **layout, int xsize, int ysize)
00040 {
00041     int i,j;
00042     int nxsize = xsize * 2 - 1;
00043     int nysize = ysize * 2 - 1;
00044 
00045     /* Allocate new layout */
00046     char **newlayout = (char **) calloc(sizeof(char *), nxsize);
00047 
00048     for (i = 0; i < nxsize; i++)
00049     {
00050         newlayout[i] = (char *) calloc(sizeof(char), nysize);
00051     }
00052 
00053     for (i = 0; i < xsize; i++)
00054     {
00055         for (j = 0; j < ysize; j++)
00056         {
00057             switch (layout[i][j])
00058             {
00059                 case '#':
00060                     expand_wall(newlayout, i, j, layout, xsize, ysize);
00061                     break;
00062 
00063                 case 'D':
00064                     expand_door(newlayout, i, j, layout, xsize, ysize);
00065                     break;
00066 
00067                 default:
00068                     expand_misc(newlayout, i, j, layout);
00069             }
00070         }
00071     }
00072 
00073     /* Free old layout */
00074     for (i = 0; i < xsize; i++)
00075     {
00076         free(layout[i]);
00077     }
00078 
00079     free(layout);
00080 
00081     return newlayout;
00082 }
00083 
00095 static void expand_misc(char **newlayout, int i, int j, char **layout)
00096 {
00097     newlayout[i * 2][j * 2] = layout[i][j];
00098 }
00099 
00113 static int calc_pattern(char ch, char **layout, int i, int j, int xsize, int ysize)
00114 {
00115     int pattern = 0;
00116 
00117     if (i + 1 < xsize && layout[i + 1][j] == ch)
00118     {
00119         pattern |= 1;
00120     }
00121 
00122     if (j + 1 < ysize)
00123     {
00124         if (layout[i][j + 1] == ch)
00125         {
00126             pattern |= 2;
00127         }
00128 
00129         if (i + 1 < xsize && layout[i + 1][j + 1] == ch)
00130         {
00131             pattern |= 4;
00132         }
00133     }
00134 
00135     return pattern;
00136 }
00137 
00148 static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize)
00149 {
00150     int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
00151     int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
00152     int both_pattern = wall_pattern | door_pattern;
00153 
00154     newlayout[i * 2][j * 2] = '#';
00155 
00156     if (i + 1 < xsize)
00157     {
00158         /* join walls/doors to the right */
00159         if (both_pattern & 1)
00160         {
00161             newlayout[i * 2 + 1][j * 2] = layout[i + 1][j];
00162         }
00163     }
00164 
00165     if (j + 1 < ysize)
00166     {
00167         /* join walls/doors to the bottom */
00168         if (both_pattern & 2)
00169         {
00170             newlayout[i * 2][j * 2 + 1] = layout[i][j + 1];
00171         }
00172 
00173         if (wall_pattern == 7)
00174         {
00175             /* if orig layout is a 2x2 wall block,
00176              * we fill the result with walls. */
00177             newlayout[i * 2 + 1][j * 2 + 1] = '#';
00178         }
00179     }
00180 }
00181 
00193 static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize)
00194 {
00195     int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
00196     int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
00197     int join_pattern;
00198 
00199     /* Doors "like" to connect to walls more than other doors. If there is
00200      * a wall and another door, this door will connect to the wall and
00201      * disconnect from the other door. */
00202     if (wall_pattern & 3)
00203     {
00204         join_pattern = wall_pattern;
00205     }
00206     else
00207     {
00208         join_pattern = door_pattern;
00209     }
00210 
00211     newlayout[i * 2][j * 2] = 'D';
00212 
00213     if (i + 1 < xsize)
00214     {
00215         /* There is a door/wall to the right */
00216         if (join_pattern & 1)
00217         {
00218             newlayout[i * 2 + 1][j * 2] = 'D';
00219         }
00220     }
00221 
00222     if (j + 1 < ysize)
00223     {
00224         /* There is a door/wall below */
00225         if (join_pattern & 2)
00226         {
00227             newlayout[i * 2][j * 2 + 1] = 'D';
00228         }
00229     }
00230 }