ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/room_gen_onion.c
Revision: 1.2
Committed: Sun Aug 13 17:16:03 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
State: FILE REMOVED
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

# Content
1 /*
2 * static char *room_gen_onion_c =
3 * "$Id$";
4 */
5
6 /*
7 CrossFire, A Multiplayer game for X-windows
8
9 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28
29
30 /* The onion room generator:
31 Onion rooms are like this:
32
33 char **map_gen_onion(int xsize, int ysize, int option, int layers);
34
35 like this:
36 regular random
37 centered, linear onion bottom/right centered, nonlinear
38
39 ######################### #########################
40 # # # #
41 # ######## ########## # # #####################
42 # # # # # # #
43 # # ###### ######## # # # # #
44 # # # # # # # # ######## ########
45 # # # #### ###### # # # # # # #
46 # # # # # # # # # # # #
47 # # # ############ # # # # # # ########### ##
48 # # # # # # # # # # #
49 # # ################ # # # # # # #########
50 # # # # # # # # #
51 # #################### # # # # # #
52 # # # # # # # #
53 ######################### #########################
54
55 */
56
57
58 int *free_x_list;
59 int *free_y_list;
60 #include <global.h>
61 #include <random_map.h>
62
63 #ifndef MIN
64 #define MIN(x,y) (((x)<(y))? (x):(y))
65 #endif
66 void centered_onion(char **maze, int xsize, int ysize, int option, int layers);
67 void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers);
68 void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers);
69
70
71 void draw_onion(char **maze,float *xlocations,float *ylocations,int layers);
72 void make_doors(char **maze,float *xlocations,float *ylocations,int layers,int options);
73
74 char **map_gen_onion(int xsize, int ysize, int option, int layers) {
75 int i,j;
76
77 /* allocate that array, set it up */
78 char **maze = (char **)calloc(sizeof(char*),xsize);
79 for(i=0;i<xsize;i++) {
80 maze[i] = (char *) calloc(sizeof(char),ysize);
81 }
82
83 /* pick some random options if option = 0 */
84 if(option == 0) {
85 switch(RANDOM()%3) {
86 case 0:
87 option |= OPT_CENTERED;
88 break;
89 case 1:
90 option |= OPT_BOTTOM_C;
91 break;
92 case 2:
93 option |= OPT_BOTTOM_R;
94 break;
95 }
96 if(RANDOM()%2) option |=OPT_LINEAR;
97 if(RANDOM()%2) option |=OPT_IRR_SPACE;
98 }
99
100 /* write the outer walls, if appropriate. */
101 if(!(option & OPT_WALL_OFF )) {
102 for(i=0;i<xsize;i++)
103 maze[i][0] = maze[i][ysize-1] = '#';
104 for(j=0;j<ysize;j++)
105 maze[0][j] = maze[xsize-1][j] = '#';
106 };
107
108 if(option & OPT_WALLS_ONLY) return maze;
109
110 /* pick off the mutually exclusive options */
111 if(option & OPT_BOTTOM_R)
112 bottom_right_centered_onion(maze,xsize,ysize,option,layers);
113 else if(option & OPT_BOTTOM_C)
114 bottom_centered_onion(maze,xsize,ysize,option,layers);
115 else if(option & OPT_CENTERED)
116 centered_onion(maze,xsize,ysize,option,layers);
117
118 return maze;
119 }
120
121 void centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
122 int i,maxlayers;
123 float *xlocations;
124 float *ylocations;
125
126 maxlayers = (MIN(xsize,ysize)-2)/5;
127 if(!maxlayers) return; /* map too small to onionize */
128 if(layers > maxlayers) layers = maxlayers;
129 if(layers == 0) layers = (RANDOM() % maxlayers)+1;
130 xlocations = (float *) calloc(sizeof(float),2 * layers);
131 ylocations = (float *) calloc(sizeof(float),2 * layers);
132
133
134 /* place all the walls */
135 if(option & OPT_IRR_SPACE) /* randomly spaced */ {
136 int x_spaces_available, y_spaces_available;
137 /* the "extra" spaces available for spacing between layers */
138 x_spaces_available = (xsize -2) - 6*layers +1;
139 y_spaces_available = (ysize -2) - 6*layers +1;
140
141
142 /* pick an initial random pitch */
143 for(i=0;i<2*layers;i++) {
144 float xpitch=2,ypitch=2;
145 if(x_spaces_available>0)
146 xpitch = 2 + (RANDOM()%x_spaces_available +
147 RANDOM()%x_spaces_available +
148 RANDOM()%x_spaces_available)/3;
149
150 if(y_spaces_available>0)
151 ypitch = 2 + (RANDOM()%y_spaces_available +
152 RANDOM()%y_spaces_available +
153 RANDOM()%y_spaces_available)/3;
154 xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch;
155 ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch;
156 x_spaces_available-=xpitch -2;
157 y_spaces_available-=ypitch -2;
158 }
159
160 }
161 if(!(option&OPT_IRR_SPACE)){ /* evenly spaced */
162 float xpitch, ypitch; /* pitch of the onion layers */
163 xpitch = (xsize-2.0)/(2.0*layers+1);
164 ypitch = (ysize-2.0)/(2.0*layers+1);
165 xlocations[0] = xpitch;
166 ylocations[0] = ypitch;
167 for(i=1;i<2*layers;i++) {
168 xlocations[i] = xlocations[i-1] + xpitch;
169 ylocations[i] = ylocations[i-1] + ypitch;
170 }
171 }
172
173 /* draw all the onion boxes. */
174
175 draw_onion(maze,xlocations,ylocations,layers);
176 make_doors(maze,xlocations,ylocations,layers,option);
177
178 }
179
180 void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
181 int i,maxlayers;
182 float *xlocations;
183 float *ylocations;
184
185 maxlayers = (MIN(xsize,ysize)-2)/5;
186 if(!maxlayers) return; /* map too small to onionize */
187 if(layers > maxlayers) layers = maxlayers;
188 if(layers == 0) layers = (RANDOM() % maxlayers)+1;
189 xlocations = (float *) calloc(sizeof(float),2 * layers);
190 ylocations = (float *) calloc(sizeof(float),2 * layers);
191
192
193 /* place all the walls */
194 if(option & OPT_IRR_SPACE) /* randomly spaced */ {
195 int x_spaces_available, y_spaces_available;
196 /* the "extra" spaces available for spacing between layers */
197 x_spaces_available = (xsize -2) - 6*layers +1;
198 y_spaces_available = (ysize -2) - 3*layers +1;
199
200
201 /* pick an initial random pitch */
202 for(i=0;i<2*layers;i++) {
203 float xpitch=2,ypitch=2;
204 if(x_spaces_available>0)
205 xpitch = 2 + (RANDOM()%x_spaces_available +
206 RANDOM()%x_spaces_available +
207 RANDOM()%x_spaces_available)/3;
208
209 if(y_spaces_available>0)
210 ypitch = 2 + (RANDOM()%y_spaces_available +
211 RANDOM()%y_spaces_available +
212 RANDOM()%y_spaces_available)/3;
213 xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch;
214 if(i < layers) ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch;
215 else ylocations[i] = ysize-1;
216 x_spaces_available-=xpitch -2;
217 y_spaces_available-=ypitch -2;
218 }
219
220 }
221 if(!(option&OPT_IRR_SPACE)){ /* evenly spaced */
222 float xpitch, ypitch; /* pitch of the onion layers */
223 xpitch = (xsize-2.0)/(2.0*layers+1);
224 ypitch = (ysize-2.0)/(layers+1);
225 xlocations[0] = xpitch;
226 ylocations[0] = ypitch;
227 for(i=1;i<2*layers;i++) {
228 xlocations[i] = xlocations[i-1] + xpitch;
229 if(i < layers) ylocations[i] = ylocations[i-1] + ypitch;
230 else ylocations[i]=ysize-1;
231 }
232 }
233
234 /* draw all the onion boxes. */
235
236 draw_onion(maze,xlocations,ylocations,layers);
237 make_doors(maze,xlocations,ylocations,layers,option);
238
239 }
240
241
242 /* draw_boxes: draws the lines in the maze defining the onion layers */
243
244 void draw_onion(char **maze,float *xlocations,float *ylocations, int layers) {
245 int i,j,l;
246
247 for(l=0;l<layers;l++) {
248 int x1,x2,y1,y2;
249 /* horizontal segments */
250 y1 = (int)ylocations[l];
251 y2 = (int)ylocations[2*layers -l-1];
252 for(i=(int)xlocations[l];i<=(int)xlocations[2*layers -l -1];i++) {
253 maze[i][y1] = '#';
254 maze[i][y2] = '#';
255 }
256
257 /* vertical segments */
258 x1 = (int)xlocations[l];
259 x2 = (int)xlocations[2*layers-l-1];
260 for(j=(int)ylocations[l];j<=(int)ylocations[2*layers -l -1];j++) {
261 maze[x1][j] = '#';
262 maze[x2][j] = '#';
263 }
264
265 }
266 }
267
268 void make_doors(char **maze, float *xlocations,float *ylocations,int layers,int options) {
269 int freedoms; /* number of different walls on which we could place a door */
270 int which_wall; /* left, 1, top, 2, right, 3, bottom 4 */
271 int l,x1=0,x2,y1=0,y2;
272 freedoms = 4; /* centered */
273 if(options & OPT_BOTTOM_C) freedoms=3;
274 if(options & OPT_BOTTOM_R) freedoms=2;
275 if(layers<= 0) return;
276 /* pick which wall will have a door. */
277 which_wall = RANDOM() %freedoms + 1;
278 for(l=0;l<layers;l++) {
279 if(options & OPT_LINEAR) { /* linear door placement. */
280 switch(which_wall) {
281 case 1: { /* left hand wall */
282 x1 = (int)xlocations[l];
283 y1 = (int)( (ylocations[l] + ylocations[2*layers-l-1])/2);
284 break;
285 }
286 case 2: { /* top wall placement */
287 x1 = (int)( (xlocations[l] + xlocations[2*layers-l-1])/2);
288 y1 = (int)ylocations[l];
289 break;
290 }
291 case 3: { /* right wall placement */
292 x1 = (int)xlocations[2*layers-l-1];
293 y1 = (int)( (ylocations[l] + ylocations[2*layers-l-1])/2);
294 break;
295 }
296 case 4: { /* bottom wall placement */
297 x1 = (int)( (xlocations[l] + xlocations[2*layers-l-1])/2);
298 y1 = (int)ylocations[2*layers -l -1];
299 break;
300 }
301 }
302 }
303 else { /* random door placement. */
304 which_wall=RANDOM()%freedoms + 1;
305 switch(which_wall) {
306 case 1: { /* left hand wall */
307 x1 = (int)xlocations[l];
308 y2 = ylocations[2*layers-l-1]-ylocations[l]-1;
309 if(y2 > 0) y1 = ylocations[l]+RANDOM() %y2 + 1;
310 else y1 = ylocations[l]+1;
311 break;
312 }
313 case 2: { /* top wall placement */
314 x2 = (int)( (-xlocations[l] + xlocations[2*layers-l-1]))-1;
315 if (x2 > 0) x1 = xlocations[l]+RANDOM()%x2 + 1;
316 else x1 = xlocations[l]+1;
317 y1 = (int)ylocations[l];
318 break;
319 }
320 case 3: { /* right wall placement */
321 x1 = (int)xlocations[2*layers-l-1];
322 y2 = (int)( (-ylocations[l] + ylocations[2*layers-l-1]))-1;
323 if(y2 > 0) y1 = ylocations[l]+RANDOM() %y2 + 1;
324 else y1 = ylocations[l]+1;
325
326 break;
327 }
328 case 4: { /* bottom wall placement */
329 x2 = (int)( (-xlocations[l] + xlocations[2*layers-l-1]))-1;
330 if (x2 > 0) x1 = xlocations[l]+RANDOM()%x2 + 1;
331 else x1 = xlocations[l]+1;
332 y1 = (int)ylocations[2*layers-l-1];
333 break;
334 }
335
336 }
337 }
338 if(options & OPT_NO_DOORS)
339 maze[x1][y1] = '#'; /* no door. */
340 else
341 maze[x1][y1] = 'D'; /* write the door */
342
343 }
344 /* mark the center of the maze with a C */
345 l = layers -1;
346 x1 = (int) (xlocations[l] + xlocations[2*layers -l -1])/2;
347 y1 = (int) (ylocations[l] + ylocations[2*layers -l -1])/2;
348 maze[x1][y1] = 'C';
349
350 /* not needed anymore */
351 free(xlocations);
352 free(ylocations);
353
354 }
355
356 void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers){
357 int i,maxlayers;
358 float *xlocations;
359 float *ylocations;
360
361 maxlayers = (MIN(xsize,ysize)-2)/5;
362 if(!maxlayers) return; /* map too small to onionize */
363 if(layers > maxlayers) layers = maxlayers;
364 if(layers == 0) layers = (RANDOM() % maxlayers)+1;
365 xlocations = (float *) calloc(sizeof(float),2 * layers);
366 ylocations = (float *) calloc(sizeof(float),2 * layers);
367
368
369 /* place all the walls */
370 if(option & OPT_IRR_SPACE) /* randomly spaced */ {
371 int x_spaces_available, y_spaces_available;
372 /* the "extra" spaces available for spacing between layers */
373 x_spaces_available = (xsize -2) - 3*layers +1;
374 y_spaces_available = (ysize -2) - 3*layers +1;
375
376
377 /* pick an initial random pitch */
378 for(i=0;i<2*layers;i++) {
379 float xpitch=2,ypitch=2;
380 if(x_spaces_available>0)
381 xpitch = 2 + (RANDOM()%x_spaces_available +
382 RANDOM()%x_spaces_available +
383 RANDOM()%x_spaces_available)/3;
384
385 if(y_spaces_available>0)
386 ypitch = 2 + (RANDOM()%y_spaces_available +
387 RANDOM()%y_spaces_available +
388 RANDOM()%y_spaces_available)/3;
389 if(i < layers) xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch;
390 else xlocations[i] = xsize-1;
391
392 if(i < layers) ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch;
393 else ylocations[i] = ysize-1;
394 x_spaces_available-=xpitch -2;
395 y_spaces_available-=ypitch -2;
396 }
397
398 }
399 if(!(option&OPT_IRR_SPACE)){ /* evenly spaced */
400 float xpitch, ypitch; /* pitch of the onion layers */
401 xpitch = (xsize-2.0)/(2.0*layers+1);
402 ypitch = (ysize-2.0)/(layers+1);
403 xlocations[0] = xpitch;
404 ylocations[0] = ypitch;
405 for(i=1;i<2*layers;i++) {
406 if(i < layers) xlocations[i] = xlocations[i-1] + xpitch;
407 else xlocations[i]=xsize-1;
408 if(i < layers) ylocations[i] = ylocations[i-1] + ypitch;
409 else ylocations[i]=ysize-1;
410 }
411 }
412
413 /* draw all the onion boxes. */
414
415 draw_onion(maze,xlocations,ylocations,layers);
416 make_doors(maze,xlocations,ylocations,layers,option);
417
418 }