Crossfire Server, Trunk  R213250
room_gen_spiral.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
21 #include "global.h"
22 
23 #include <stdlib.h>
24 
25 #include "random_map.h"
26 
31 #define RANDOM_OPTIONS 0
32 #define REGULAR_SPIRAL 1
33 #define FINE_SPIRAL 2
34 #define FIT_SPIRAL 4
35 #define MAX_SPIRAL_OPT 8
37 
38 #include <math.h>
39 
40 #ifndef MIN
41 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
42 #endif
43 #ifndef MAX
44 #define MAX(x, y) (((x) < (y)) ? (y) : (x))
45 #endif
46 
47 #define MAX_FINE .454545
48 
49 extern int surround_check(char **maze, int i, int j, int xsize, int ysize);
50 
61 char **map_gen_spiral(int xsize, int ysize, int option, int _unused_layers)
62 {
63  int i, j;
64  float parm = 0;
65  float x = 0, y = 0;
66  int ic, jc;
67  float SizeX, SizeY;
68  float xscale, yscale;
69 
70  (void)_unused_layers;
71 
72  /* allocate that array, set it up */
73  char **maze = (char **)calloc(sizeof(char *), xsize);
74 
75  for (i = 0; i < xsize; i++) {
76  maze[i] = (char *)calloc(sizeof(char), ysize);
77  }
78 
79  /* slightly easier to fill and then cut */
80  for (i = 0; i < xsize; i++)
81  for (j = 0; j < ysize; j++) {
82  maze[i][j] = '#';
83  }
84 
85  ic = xsize/2;
86  jc = ysize/2;
87  SizeX = xsize/2-2;
88  SizeY = ysize/2-2;
89 
90  /* select random options if necessary */
91  if (option == 0) {
92  option = RANDOM()%MAX_SPIRAL_OPT;
93  }
94 
95  /* the order in which these are evaluated matters*/
96 
97  /* the following two are mutually exclusive.
98  pick one if they're both set. */
99  if ((option&REGULAR_SPIRAL) && (option&FIT_SPIRAL)) {
100  /* unset REGULAR_SPIRAL half the time */
101  if (RANDOM()%2 && (option&REGULAR_SPIRAL)) {
102  option -= REGULAR_SPIRAL;
103  } else {
104  option -= FIT_SPIRAL;
105  }
106  }
107 
108  xscale = yscale = MAX_FINE; /* fine spiral */
109 
110  /* choose the spiral pitch */
111  if (!(option&FINE_SPIRAL)) {
112  float pitch = (RANDOM()%5)/10.+10./22.;
113 
114  xscale = yscale = pitch;
115  }
116 
117  if ((option&FIT_SPIRAL) && (xsize != ysize)) {
118  if (xsize > ysize) {
119  xscale *= (float)xsize/(float)ysize;
120  } else {
121  yscale *= (float)ysize/(float)xsize;
122  }
123  }
124 
125  if (option&REGULAR_SPIRAL) {
126  float scale = MIN(xscale, yscale);
127 
128  xscale = yscale = scale;
129  }
130 
131  /* cut out the spiral */
132  while ((fabsf(x) < SizeX) && (fabsf(y) < SizeY)) {
133  x = parm*cos(parm)*xscale;
134  y = parm*sin(parm)*yscale;
135  maze[(int)(ic+x)][(int)(jc+y)] = '\0';
136  parm += 0.01;
137  };
138 
139  maze[(int)(ic+x+0.5)][(int)(jc+y+0.5)] = '<';
140 
141  /* cut out the center in a 2x2 and place the center and downexit */
142  maze[ic][jc+1] = '>';
143  maze[ic][jc] = 'C';
144 
145  return maze;
146 }
147 
158 void connect_spirals(int xsize, int ysize, int sym, char **layout)
159 {
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  }
168  /* go right */
169  for (i = ic+1, j = jc; i < xsize-1 && layout[i][j] == '#'; i++) {
170  layout[i][j] = 0;
171  }
172  }
173 
174  if (sym == Y_SYM) {
175  layout[ic][jc] = 0;
176  /* go up */
177  for (i = ic, j = jc-1; j > 0 && layout[i][j] == '#'; j--) {
178  layout[i][j] = 0;
179  }
180  /* go down */
181  for (i = ic, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++) {
182  layout[i][j] = 0;
183  }
184  }
185 
186  if (sym == XY_SYM) {
187  /* go left from map center */
188  layout[ic][jc/2] = 0;
189  layout[ic/2][jc] = 0;
190  layout[ic][jc/2+jc] = 0;
191  layout[ic/2+ic][jc] = 0;
192  for (i = ic-1, j = jc/2; i > 0 && layout[i][j] == '#'; i--) {
193  layout[i][j+jc] = 0;
194  layout[i][j] = 0;
195  }
196  /* go right */
197  for (i = ic+1, j = jc/2; i < xsize-1 && layout[i][j] == '#'; i++) {
198  layout[i][j+jc] = 0;
199  layout[i][j] = 0;
200  }
201  /* go up */
202  for (i = ic/2, j = jc-1; j > 0 && layout[i][j] == '#'; j--) {
203  layout[i][j] = 0;
204  layout[i+ic][j] = 0;
205  }
206  /* go down */
207  for (i = ic/2, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++) {
208  layout[i][j] = 0;
209  layout[i+ic][j] = 0;
210  }
211  }
212 
213  /* get rid of bad doors. */
214  for (i = 0; i < xsize; i++)
215  for (j = 0; j < ysize; j++) {
216  if (layout[i][j] == 'D') { /* remove bad door. */
217  int si = surround_check(layout, i, j, xsize, ysize);
218  if (si != 3 && si != 12) {
219  layout[i][j] = 0;
220  /* back up and recheck any nearby doors */
221  i = 0;
222  j = 0;
223  }
224  }
225  }
226 }
char ** map_gen_spiral(int xsize, int ysize, int option, int _unused_layers)
#define MAX_SPIRAL_OPT
#define FINE_SPIRAL
#define FIT_SPIRAL
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:303
#define MIN(x, y)
#define MAX_FINE
#define RANDOM()
Definition: define.h:681
#define Y_SYM
Definition: random_map.h:141
#define X_SYM
Definition: random_map.h:140
#define XY_SYM
Definition: random_map.h:142
Definition: main.c:88