Crossfire Server, Trunk  R20513
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)
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  /* allocate that array, set it up */
71  char **maze = (char **)calloc(sizeof(char *), xsize);
72 
73  for (i = 0; i < xsize; i++) {
74  maze[i] = (char *)calloc(sizeof(char), ysize);
75  }
76 
77  /* slightly easier to fill and then cut */
78  for (i = 0; i < xsize; i++)
79  for (j = 0; j < ysize; j++) {
80  maze[i][j] = '#';
81  }
82 
83  ic = xsize/2;
84  jc = ysize/2;
85  SizeX = xsize/2-2;
86  SizeY = ysize/2-2;
87 
88  /* select random options if necessary */
89  if (option == 0) {
90  option = RANDOM()%MAX_SPIRAL_OPT;
91  }
92 
93  /* the order in which these are evaluated matters*/
94 
95  /* the following two are mutually exclusive.
96  pick one if they're both set. */
97  if ((option&REGULAR_SPIRAL) && (option&FIT_SPIRAL)) {
98  /* unset REGULAR_SPIRAL half the time */
99  if (RANDOM()%2 && (option&REGULAR_SPIRAL)) {
100  option -= REGULAR_SPIRAL;
101  } else {
102  option -= FIT_SPIRAL;
103  }
104  }
105 
106  xscale = yscale = MAX_FINE; /* fine spiral */
107 
108  /* choose the spiral pitch */
109  if (!(option&FINE_SPIRAL)) {
110  float pitch = (RANDOM()%5)/10.+10./22.;
111 
112  xscale = yscale = pitch;
113  }
114 
115  if ((option&FIT_SPIRAL) && (xsize != ysize)) {
116  if (xsize > ysize) {
117  xscale *= (float)xsize/(float)ysize;
118  } else {
119  yscale *= (float)ysize/(float)xsize;
120  }
121  }
122 
123  if (option&REGULAR_SPIRAL) {
124  float scale = MIN(xscale, yscale);
125 
126  xscale = yscale = scale;
127  }
128 
129  /* cut out the spiral */
130  while ((abs(x) < SizeX) && (abs(y) < SizeY)) {
131  x = parm*cos(parm)*xscale;
132  y = parm*sin(parm)*yscale;
133  maze[(int)(ic+x)][(int)(jc+y)] = '\0';
134  parm += 0.01;
135  };
136 
137  maze[(int)(ic+x+0.5)][(int)(jc+y+0.5)] = '<';
138 
139  /* cut out the center in a 2x2 and place the center and downexit */
140  maze[ic][jc+1] = '>';
141  maze[ic][jc] = 'C';
142 
143  return maze;
144 }
145 
156 void connect_spirals(int xsize, int ysize, int sym, char **layout)
157 {
158  int i, j, ic = xsize/2, jc = ysize/2;
159 
160  if (sym == X_SYM) {
161  layout[ic][jc] = 0;
162  /* go left from map center */
163  for (i = ic-1, j = jc; i > 0 && layout[i][j] == '#'; i--) {
164  layout[i][j] = 0;
165  }
166  /* go right */
167  for (i = ic+1, j = jc; i < xsize-1 && layout[i][j] == '#'; i++) {
168  layout[i][j] = 0;
169  }
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  }
178  /* go down */
179  for (i = ic, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++) {
180  layout[i][j] = 0;
181  }
182  }
183 
184  if (sym == XY_SYM) {
185  /* go left from map center */
186  layout[ic][jc/2] = 0;
187  layout[ic/2][jc] = 0;
188  layout[ic][jc/2+jc] = 0;
189  layout[ic/2+ic][jc] = 0;
190  for (i = ic-1, j = jc/2; i > 0 && layout[i][j] == '#'; i--) {
191  layout[i][j+jc] = 0;
192  layout[i][j] = 0;
193  }
194  /* go right */
195  for (i = ic+1, j = jc/2; i < xsize-1 && layout[i][j] == '#'; i++) {
196  layout[i][j+jc] = 0;
197  layout[i][j] = 0;
198  }
199  /* go up */
200  for (i = ic/2, j = jc-1; j > 0 && layout[i][j] == '#'; j--) {
201  layout[i][j] = 0;
202  layout[i+ic][j] = 0;
203  }
204  /* go down */
205  for (i = ic/2, j = jc+1; j < ysize-1 && layout[i][j] == '#'; j++) {
206  layout[i][j] = 0;
207  layout[i+ic][j] = 0;
208  }
209  }
210 
211  /* get rid of bad doors. */
212  for (i = 0; i < xsize; i++)
213  for (j = 0; j < ysize; j++) {
214  if (layout[i][j] == 'D') { /* remove bad door. */
215  int si = surround_check(layout, i, j, xsize, ysize);
216  if (si != 3 && si != 12) {
217  layout[i][j] = 0;
218  /* back up and recheck any nearby doors */
219  i = 0;
220  j = 0;
221  }
222  }
223  }
224 }
#define MAX_SPIRAL_OPT
this should be 2x the last real option
Random map related variables.
Global type definitions and header inclusions.
#define FINE_SPIRAL
uses the min.
#define FIT_SPIRAL
scale to a rectangular region, not square
char ** map_gen_spiral(int xsize, int ysize, int option)
Generates a spiral layout.
void connect_spirals(int xsize, int ysize, int sym, char **layout)
Connects disjoint spirals which may result from the symmetrization process.
#define REGULAR_SPIRAL
Regular spiral–distance increases constantly.
int surround_check(char **maze, int i, int j, int xsize, int ysize)
Checks free spots around a spot.
Definition: rogue_layout.c:303
#define MIN(x, y)
#define MAX_FINE
#define RANDOM()
Definition: define.h:679
#define Y_SYM
Horizontal symmetry.
Definition: random_map.h:141
#define X_SYM
Vertical symmetry.
Definition: random_map.h:140
#define XY_SYM
Reflection.
Definition: random_map.h:142
Definition: main.c:88