Atrinik Server  4.0
room_gen_spiral.c
Go to the documentation of this file.
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 
30 #include <global.h>
31 
36 #define RANDOM_OPTIONS 0
37 
38 #define REGULAR_SPIRAL 1
39 
40 #define FINE_SPIRAL 2
41 
42 #define FIT_SPIRAL 4
43 
44 #define MAX_SPIRAL_OPT 8
45 
47 #define MINDIST 3
48 
49 #define MAX_FINE .454545
50 
62 char **map_gen_spiral(int xsize, int ysize, int option)
63 {
64  int i, j, ic, jc;
65  float parm = 0, x = 0, y = 0, SizeX, SizeY, xscale, yscale;
66 
67  /* Allocate that array, set it up */
68  char **maze = ecalloc(sizeof(char *), xsize);
69 
70  for (i = 0; i < xsize; i++) {
71  maze[i] = ecalloc(sizeof(char), ysize);
72  }
73 
74  /* Slightly easier to fill and then cut */
75  for (i = 0; i < xsize; i++) {
76  for (j = 0; j < ysize; j++) {
77  maze[i][j] = '#';
78  }
79  }
80 
81  ic = xsize / 2;
82  jc = ysize / 2;
83 
84  SizeX = (float) xsize / 2.0f - 2.0f;
85  SizeY = (float) ysize / 2.0f - 2.0f;
86 
87  /* Select random options if necessary */
88  if (option == 0) {
89  option = rndm(0, MAX_SPIRAL_OPT);
90  }
91 
92  /* the order in which these are evaluated matters */
93 
94  /* the following two are mutually exclusive.
95  * pick one if they're both set. */
96  if ((option & REGULAR_SPIRAL) && (option & FIT_SPIRAL)) {
97  /* unset REGULAR_SPIRAL half the time */
98  if (rndm_chance(2) && (option & REGULAR_SPIRAL)) {
99  option -= REGULAR_SPIRAL;
100  } else {
101  option -= FIT_SPIRAL;
102  }
103  }
104 
105  /* fine spiral */
106  xscale = yscale = (float) MAX_FINE;
107 
108  /* choose the spiral pitch */
109  if (!(option & FINE_SPIRAL)) {
110  float pitch = (float) (RANDOM() % 5) / 10.0f + 10.0f / 22.0f;
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  xscale = yscale = scale;
126  }
127 
128  /* cut out the spiral */
129  while ((FABS(x) < SizeX) && (FABS(y) < SizeY)) {
130  x = parm * (float) cos((double) parm) * xscale;
131  y = parm * (float) sin((double) parm) * yscale;
132 
133  maze[(int) (ic + x)][(int) (jc + y)] = '\0';
134 
135  parm += 0.01f;
136  }
137 
138  maze[(int) (ic + x + 0.5)][(int) (jc + y + 0.5)] = '<';
139 
140  /* Cut out the center in a 2x2 and place the center and downexit */
141  maze[ic][jc + 1] = '>';
142  maze[ic][jc] = 'C';
143 
144  return maze;
145 }
146 
159 void connect_spirals(int xsize, int ysize, int sym, char **layout)
160 {
161  int i, j, ic = xsize / 2, jc = ysize / 2;
162 
163  if (sym == X_SYM) {
164  layout[ic][jc] = 0;
165 
166  /* go left from map center */
167  for (i = ic - 1, j = jc; i > 0 && layout[i][j] == '#'; i--) {
168  layout[i][j] = 0;
169  }
170 
171  /* go right */
172  for (i = ic + 1, j = jc; i < xsize - 1 && layout[i][j] == '#'; i++) {
173  layout[i][j] = 0;
174  }
175  }
176 
177  if (sym == Y_SYM) {
178  layout[ic][jc] = 0;
179 
180  /* go up */
181  for (i = ic, j = jc - 1; j > 0 && layout[i][j] == '#'; j--) {
182  layout[i][j] = 0;
183  }
184 
185  /* go down */
186  for (i = ic, j = jc + 1; j < ysize - 1 && layout[i][j] == '#'; j++) {
187  layout[i][j] = 0;
188  }
189  }
190 
191  if (sym == XY_SYM) {
192  layout[ic][jc / 2] = 0;
193  layout[ic / 2][jc] = 0;
194  layout[ic][jc / 2 + jc] = 0;
195  layout[ic / 2 + ic][jc] = 0;
196 
197  /* go left from map center */
198  for (i = ic - 1, j = jc / 2; i > 0 && layout[i][j] == '#'; i--) {
199  layout[i][j + jc] = 0;
200  layout[i][j] = 0;
201  }
202 
203  /* go right */
204  for (i = ic + 1, j = jc / 2; i < xsize - 1 && layout[i][j] == '#'; i++) {
205  layout[i][j + jc] = 0;
206  layout[i][j] = 0;
207  }
208 
209  /* go up */
210  for (i = ic / 2, j = jc - 1; j > 0 && layout[i][j] == '#'; j--) {
211  layout[i][j] = 0;
212  layout[i + ic][j] = 0;
213  }
214 
215  /* go down */
216  for (i = ic / 2, j = jc + 1; j < ysize - 1 && layout[i][j] == '#'; j++) {
217  layout[i][j] = 0;
218  layout[i + ic][j] = 0;
219  }
220  }
221 
222  /* Get rid of bad doors. */
223  for (i = 0; i < xsize; i++) {
224  for (j = 0; j < ysize; j++) {
225  /* Remove bad door. */
226  if (layout[i][j] == 'D') {
227  int si = surround_check(layout, i, j, xsize, ysize);
228 
229  if (si != 3 && si != 12) {
230  layout[i][j] = 0;
231 
232  /* Back up and recheck any nearby doors */
233  i = 0;
234  j = 0;
235  }
236  }
237  }
238  }
239 }
#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 **layout, int i, int j, int Xsize, int Ysize)
Definition: rogue_layout.c:71
#define Y_SYM
Definition: random_map.h:185
#define X_SYM
Definition: random_map.h:183
#define XY_SYM
Definition: random_map.h:187