Crossfire Server, Branches 1.12  R18729
room_gen_spiral.c
Go to the documentation of this file.
1 /*
2  CrossFire, A Multiplayer game for X-windows
3 
4  Copyright (C) 1994 Mark Wedel
5  Copyright (C) 1992 Frank Tore Johansen
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21  The author can be reached via e-mail to mark@pyramid.com
22 */
23 
24 
31 #include <global.h>
32 #include <random_map.h>
33 
38 #define RANDOM_OPTIONS 0
39 #define REGULAR_SPIRAL 1
40 #define FINE_SPIRAL 2
41 #define FIT_SPIRAL 4
42 #define MAX_SPIRAL_OPT 8
44 
45 #include <math.h>
46 
47 #ifndef MIN
48 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
49 #endif
50 #ifndef MAX
51 #define MAX(x, y) (((x) < (y)) ? (y) : (x))
52 #endif
53 
54 #define MAX_FINE .454545
55 
56 extern int surround_check(char **maze, int i, int j, int xsize, int ysize);
57 
68 char **map_gen_spiral(int xsize, int ysize, int option) {
69  int i, j;
70  float parm = 0;
71  float x = 0, y = 0;
72  int ic, jc;
73  float SizeX, SizeY;
74  float xscale, yscale;
75 
76  /* allocate that array, set it up */
77  char **maze = (char **)calloc(sizeof(char *), xsize);
78 
79  for (i = 0; i < xsize; i++) {
80  maze[i] = (char *)calloc(sizeof(char), ysize);
81  }
82 
83  /* slightly easier to fill and then cut */
84  for (i = 0; i < xsize; i++)
85  for (j = 0; j < ysize; j++)
86  maze[i][j] = '#';
87 
88  ic = xsize/2;
89  jc = ysize/2;
90  SizeX = xsize/2-2;
91  SizeY = ysize/2-2;
92 
93  /* select random options if necessary */
94  if (option == 0) {
95  option = RANDOM()%MAX_SPIRAL_OPT;
96  }
97 
98  /* the order in which these are evaluated matters*/
99 
100  /* the following two are mutually exclusive.
101  pick one if they're both set. */
102  if ((option&REGULAR_SPIRAL) && (option&FIT_SPIRAL)) {
103  /* unset REGULAR_SPIRAL half the time */
104  if (RANDOM()%2 && (option&REGULAR_SPIRAL))
105  option -= REGULAR_SPIRAL;
106  else
107  option -= FIT_SPIRAL;
108  }
109 
110  xscale = yscale = MAX_FINE; /* fine spiral */
111 
112  /* choose the spiral pitch */
113  if (!(option&FINE_SPIRAL)) {
114  float pitch = (RANDOM()%5)/10.+10./22.;
115 
116  xscale = yscale = pitch;
117  }
118 
119  if ((option&FIT_SPIRAL) && (xsize != ysize)) {
120  if (xsize > ysize)
121  xscale *= (float)xsize/(float)ysize;
122  else
123  yscale *= (float)ysize/(float)xsize;
124  }
125 
126  if (option&REGULAR_SPIRAL) {
127  float scale = MIN(xscale, yscale);
128 
129  xscale = yscale = scale;
130  }
131 
132  /* cut out the spiral */
133  while ((abs(x) < SizeX) && (abs(y) < SizeY)) {
134  x = parm*cos(parm)*xscale;
135  y = parm*sin(parm)*yscale;
136  maze[(int)(ic+x)][(int)(jc+y)] = '\0';
137  parm += 0.01;
138  };
139 
140  maze[(int)(ic+x+0.5)][(int)(jc+y+0.5)] = '<';
141 
142  /* cut out the center in a 2x2 and place the center and downexit */
143  maze[ic][jc+1] = '>';
144  maze[ic][jc] = 'C';
145 
146  return maze;
147 }
148 
159 void connect_spirals(int xsize, int ysize, int sym, char **layout) {
160  int i, j, ic = xsize/2, jc = ysize/2;
161 
162  if (sym == X_SYM) {
163  layout[ic][jc] = 0;
164  /* go left from map center */
165  for (i = ic-1, j = jc; i > 0 && layout[i][j] == '#'; i--)
166  layout[i][j] = 0;
167  /* go right */
168  for (i = ic+1, j = jc; i < xsize-1 && layout[i][j] == '#'; i++)
169  layout[i][j] = 0;
170  }
171 
172  if (sym == Y_SYM) {
173  layout[ic][jc] = 0;
174  /* go up */
175  for (i = ic, j = jc-1; j > 0 && layout[i][j] == '#'; j--)
176  layout[i][j] = 0;
177  /* go down */
178  for (i = ic, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++)
179  layout[i][j] = 0;
180  }
181 
182  if (sym == XY_SYM) {
183  /* go left from map center */
184  layout[ic][jc/2] = 0;
185  layout[ic/2][jc] = 0;
186  layout[ic][jc/2+jc] = 0;
187  layout[ic/2+ic][jc] = 0;
188  for (i = ic-1, j = jc/2; i > 0 && layout[i][j] == '#'; i--) {
189  layout[i][j+jc] = 0;
190  layout[i][j] = 0;
191  }
192  /* go right */
193  for (i = ic+1, j = jc/2; i < xsize-1 && layout[i][j] == '#'; i++) {
194  layout[i][j+jc] = 0;
195  layout[i][j] = 0;
196  }
197  /* go up */
198  for (i = ic/2, j = jc-1; j > 0 && layout[i][j] == '#'; j--) {
199  layout[i][j] = 0;
200  layout[i+ic][j] = 0;
201  }
202  /* go down */
203  for (i = ic/2, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++) {
204  layout[i][j] = 0;
205  layout[i+ic][j] = 0;
206  }
207  }
208 
209  /* get rid of bad doors. */
210  for (i = 0; i < xsize; i++)
211  for (j = 0; j < ysize; j++) {
212  if (layout[i][j] == 'D') { /* remove bad door. */
213  int si = surround_check(layout, i, j, xsize, ysize);
214  if (si != 3 && si != 12) {
215  layout[i][j] = 0;
216  /* back up and recheck any nearby doors */
217  i = 0;
218  j = 0;
219  }
220  }
221  }
222 }
#define MAX_SPIRAL_OPT
#define FINE_SPIRAL
#define FIT_SPIRAL
char ** map_gen_spiral(int xsize, int ysize, int option)
void connect_spirals(int xsize, int ysize, int sym, char **layout)
#define REGULAR_SPIRAL
int surround_check(char **maze, int i, int j, int xsize, int ysize)
Definition: rogue_layout.c:44
#define MIN(x, y)
#define MAX_FINE
#define Y_SYM
Definition: random_map.h:126
#define X_SYM
Definition: random_map.h:125
#define XY_SYM
Definition: random_map.h:127