Atrinik Server  4.0
expand2x.c
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
25 #include <global.h>
26 
27 static void expand_misc(char **newlayout, int i, int j, char **layout);
28 static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize);
29 static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize);
30 
43 char **expand2x(char **layout, int xsize, int ysize)
44 {
45  int i, j;
46  int nxsize = xsize * 2 - 1;
47  int nysize = ysize * 2 - 1;
48 
49  /* Allocate new layout */
50  char **newlayout = ecalloc(sizeof(char *), nxsize);
51 
52  for (i = 0; i < nxsize; i++) {
53  newlayout[i] = ecalloc(sizeof(char), nysize);
54  }
55 
56  for (i = 0; i < xsize; i++) {
57  for (j = 0; j < ysize; j++) {
58  switch (layout[i][j]) {
59  case '#':
60  expand_wall(newlayout, i, j, layout, xsize, ysize);
61  break;
62 
63  case 'D':
64  expand_door(newlayout, i, j, layout, xsize, ysize);
65  break;
66 
67  default:
68  expand_misc(newlayout, i, j, layout);
69  }
70  }
71  }
72 
73  /* Free old layout */
74  for (i = 0; i < xsize; i++) {
75  efree(layout[i]);
76  }
77 
78  efree(layout);
79 
80  return newlayout;
81 }
82 
99 static void expand_misc(char **newlayout, int i, int j, char **layout)
100 {
101  newlayout[i * 2][j * 2] = layout[i][j];
102 }
103 
125 static int calc_pattern(char ch, char **layout, int i, int j, int xsize, int ysize)
126 {
127  int pattern = 0;
128 
129  if (i + 1 < xsize && layout[i + 1][j] == ch) {
130  pattern |= 1;
131  }
132 
133  if (j + 1 < ysize) {
134  if (layout[i][j + 1] == ch) {
135  pattern |= 2;
136  }
137 
138  if (i + 1 < xsize && layout[i + 1][j + 1] == ch) {
139  pattern |= 4;
140  }
141  }
142 
143  return pattern;
144 }
145 
163 static void expand_wall(char **newlayout, int i, int j, char **layout, int xsize, int ysize)
164 {
165  int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
166  int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
167  int both_pattern = wall_pattern | door_pattern;
168 
169  newlayout[i * 2][j * 2] = '#';
170 
171  if (i + 1 < xsize) {
172  /* join walls/doors to the right */
173  if (both_pattern & 1) {
174  newlayout[i * 2 + 1][j * 2] = layout[i + 1][j];
175  }
176  }
177 
178  if (j + 1 < ysize) {
179  /* join walls/doors to the bottom */
180  if (both_pattern & 2) {
181  newlayout[i * 2][j * 2 + 1] = layout[i][j + 1];
182  }
183 
184  if (wall_pattern == 7) {
185  /* if orig layout is a 2x2 wall block,
186  * we fill the result with walls. */
187  newlayout[i * 2 + 1][j * 2 + 1] = '#';
188  }
189  }
190 }
191 
210 static void expand_door(char **newlayout, int i, int j, char **layout, int xsize, int ysize)
211 {
212  int wall_pattern = calc_pattern('#', layout, i, j, xsize, ysize);
213  int door_pattern = calc_pattern('D', layout, i, j, xsize, ysize);
214  int join_pattern;
215 
216  /* Doors "like" to connect to walls more than other doors. If there is
217  * a wall and another door, this door will connect to the wall and
218  * disconnect from the other door. */
219  if (wall_pattern & 3) {
220  join_pattern = wall_pattern;
221  } else {
222  join_pattern = door_pattern;
223  }
224 
225  newlayout[i * 2][j * 2] = 'D';
226 
227  if (i + 1 < xsize) {
228  /* There is a door/wall to the right */
229  if (join_pattern & 1) {
230  newlayout[i * 2 + 1][j * 2] = 'D';
231  }
232  }
233 
234  if (j + 1 < ysize) {
235  /* There is a door/wall below */
236  if (join_pattern & 2) {
237  newlayout[i * 2][j * 2 + 1] = 'D';
238  }
239  }
240 }