ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/room_gen_onion.C
Revision: 1.2
Committed: Tue Aug 29 08:01:36 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.1: +178 -178 lines
Log Message:
expand initial tabs to spaces

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *room_gen_onion_c =
3 root 1.2 * "$Id: room_gen_onion.C,v 1.1 2006-08-13 17:16:03 elmex Exp $";
4 elmex 1.1 */
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     #include <global.h>
59     #include <random_map.h>
60    
61     #ifndef MIN
62     #define MIN(x,y) (((x)<(y))? (x):(y))
63     #endif
64     void centered_onion(char **maze, int xsize, int ysize, int option, int layers);
65     void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers);
66     void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers);
67    
68    
69     void draw_onion(char **maze,float *xlocations,float *ylocations,int layers);
70     void make_doors(char **maze,float *xlocations,float *ylocations,int layers,int options);
71    
72     char **map_gen_onion(int xsize, int ysize, int option, int layers) {
73     int i,j;
74    
75     /* allocate that array, set it up */
76     char **maze = (char **)calloc(sizeof(char*),xsize);
77     for(i=0;i<xsize;i++) {
78     maze[i] = (char *) calloc(sizeof(char),ysize);
79     }
80    
81     /* pick some random options if option = 0 */
82     if(option == 0) {
83 root 1.2 switch(RANDOM()%3) {
84     case 0:
85     option |= OPT_CENTERED;
86     break;
87     case 1:
88     option |= OPT_BOTTOM_C;
89     break;
90     case 2:
91     option |= OPT_BOTTOM_R;
92     break;
93     }
94     if(RANDOM()%2) option |=OPT_LINEAR;
95     if(RANDOM()%2) option |=OPT_IRR_SPACE;
96 elmex 1.1 }
97    
98     /* write the outer walls, if appropriate. */
99     if(!(option & OPT_WALL_OFF )) {
100     for(i=0;i<xsize;i++)
101 root 1.2 maze[i][0] = maze[i][ysize-1] = '#';
102 elmex 1.1 for(j=0;j<ysize;j++)
103 root 1.2 maze[0][j] = maze[xsize-1][j] = '#';
104 elmex 1.1 };
105    
106     if(option & OPT_WALLS_ONLY) return maze;
107    
108     /* pick off the mutually exclusive options */
109     if(option & OPT_BOTTOM_R)
110     bottom_right_centered_onion(maze,xsize,ysize,option,layers);
111     else if(option & OPT_BOTTOM_C)
112     bottom_centered_onion(maze,xsize,ysize,option,layers);
113     else if(option & OPT_CENTERED)
114     centered_onion(maze,xsize,ysize,option,layers);
115    
116     return maze;
117     }
118    
119     void centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
120     int i,maxlayers;
121     float *xlocations;
122     float *ylocations;
123    
124     maxlayers = (MIN(xsize,ysize)-2)/5;
125     if(!maxlayers) return; /* map too small to onionize */
126     if(layers > maxlayers) layers = maxlayers;
127     if(layers == 0) layers = (RANDOM() % maxlayers)+1;
128     xlocations = (float *) calloc(sizeof(float),2 * layers);
129     ylocations = (float *) calloc(sizeof(float),2 * layers);
130    
131    
132     /* place all the walls */
133     if(option & OPT_IRR_SPACE) /* randomly spaced */ {
134 root 1.2 int x_spaces_available, y_spaces_available;
135     /* the "extra" spaces available for spacing between layers */
136     x_spaces_available = (xsize -2) - 6*layers +1;
137     y_spaces_available = (ysize -2) - 6*layers +1;
138    
139    
140     /* pick an initial random pitch */
141     for(i=0;i<2*layers;i++) {
142     float xpitch=2,ypitch=2;
143     if(x_spaces_available>0)
144     xpitch = 2 + (RANDOM()%x_spaces_available +
145     RANDOM()%x_spaces_available +
146     RANDOM()%x_spaces_available)/3;
147    
148     if(y_spaces_available>0)
149     ypitch = 2 + (RANDOM()%y_spaces_available +
150     RANDOM()%y_spaces_available +
151     RANDOM()%y_spaces_available)/3;
152     xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch;
153     ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch;
154     x_spaces_available-=(int) (xpitch -2);
155     y_spaces_available-=(int) (ypitch -2);
156     }
157    
158 elmex 1.1 }
159     if(!(option&OPT_IRR_SPACE)){ /* evenly spaced */
160     float xpitch, ypitch; /* pitch of the onion layers */
161     xpitch = (xsize-2.0)/(2.0*layers+1);
162     ypitch = (ysize-2.0)/(2.0*layers+1);
163     xlocations[0] = xpitch;
164     ylocations[0] = ypitch;
165     for(i=1;i<2*layers;i++) {
166 root 1.2 xlocations[i] = xlocations[i-1] + xpitch;
167     ylocations[i] = ylocations[i-1] + ypitch;
168 elmex 1.1 }
169     }
170    
171     /* draw all the onion boxes. */
172    
173     draw_onion(maze,xlocations,ylocations,layers);
174     make_doors(maze,xlocations,ylocations,layers,option);
175    
176     }
177    
178     void bottom_centered_onion(char **maze, int xsize, int ysize, int option, int layers) {
179     int i,maxlayers;
180     float *xlocations;
181     float *ylocations;
182    
183     maxlayers = (MIN(xsize,ysize)-2)/5;
184     if(!maxlayers) return; /* map too small to onionize */
185     if(layers > maxlayers) layers = maxlayers;
186     if(layers == 0) layers = (RANDOM() % maxlayers)+1;
187     xlocations = (float *) calloc(sizeof(float),2 * layers);
188     ylocations = (float *) calloc(sizeof(float),2 * layers);
189    
190    
191     /* place all the walls */
192     if(option & OPT_IRR_SPACE) /* randomly spaced */ {
193 root 1.2 int x_spaces_available, y_spaces_available;
194     /* the "extra" spaces available for spacing between layers */
195     x_spaces_available = (xsize -2) - 6*layers +1;
196     y_spaces_available = (ysize -2) - 3*layers +1;
197    
198    
199     /* pick an initial random pitch */
200     for(i=0;i<2*layers;i++) {
201     float xpitch=2,ypitch=2;
202     if(x_spaces_available>0)
203     xpitch = 2 + (RANDOM()%x_spaces_available +
204     RANDOM()%x_spaces_available +
205     RANDOM()%x_spaces_available)/3;
206    
207     if(y_spaces_available>0)
208     ypitch = 2 + (RANDOM()%y_spaces_available +
209     RANDOM()%y_spaces_available +
210     RANDOM()%y_spaces_available)/3;
211     xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch;
212     if(i < layers) ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch;
213     else ylocations[i] = ysize-1;
214     x_spaces_available-=(int)(xpitch -2);
215     y_spaces_available-=(int)(ypitch -2);
216     }
217    
218 elmex 1.1 }
219     if(!(option&OPT_IRR_SPACE)){ /* evenly spaced */
220     float xpitch, ypitch; /* pitch of the onion layers */
221     xpitch = (xsize-2.0)/(2.0*layers+1);
222     ypitch = (ysize-2.0)/(layers+1);
223     xlocations[0] = xpitch;
224     ylocations[0] = ypitch;
225     for(i=1;i<2*layers;i++) {
226 root 1.2 xlocations[i] = xlocations[i-1] + xpitch;
227     if(i < layers) ylocations[i] = ylocations[i-1] + ypitch;
228     else ylocations[i]=ysize-1;
229 elmex 1.1 }
230     }
231    
232     /* draw all the onion boxes. */
233    
234     draw_onion(maze,xlocations,ylocations,layers);
235     make_doors(maze,xlocations,ylocations,layers,option);
236    
237     }
238    
239    
240     /* draw_boxes: draws the lines in the maze defining the onion layers */
241    
242     void draw_onion(char **maze,float *xlocations,float *ylocations, int layers) {
243     int i,j,l;
244    
245     for(l=0;l<layers;l++) {
246 root 1.2 int x1,x2,y1,y2;
247     /* horizontal segments */
248     y1 = (int)ylocations[l];
249     y2 = (int)ylocations[2*layers -l-1];
250     for(i=(int)xlocations[l];i<=(int)xlocations[2*layers -l -1];i++) {
251     maze[i][y1] = '#';
252     maze[i][y2] = '#';
253     }
254    
255     /* vertical segments */
256     x1 = (int)xlocations[l];
257     x2 = (int)xlocations[2*layers-l-1];
258     for(j=(int)ylocations[l];j<=(int)ylocations[2*layers -l -1];j++) {
259     maze[x1][j] = '#';
260     maze[x2][j] = '#';
261     }
262    
263 elmex 1.1 }
264     }
265    
266     void make_doors(char **maze, float *xlocations,float *ylocations,int layers,int options) {
267     int freedoms; /* number of different walls on which we could place a door */
268     int which_wall; /* left, 1, top, 2, right, 3, bottom 4 */
269     int l,x1=0,x2,y1=0,y2;
270     freedoms = 4; /* centered */
271     if(options & OPT_BOTTOM_C) freedoms=3;
272     if(options & OPT_BOTTOM_R) freedoms=2;
273     if(layers<= 0) return;
274     /* pick which wall will have a door. */
275     which_wall = RANDOM() %freedoms + 1;
276     for(l=0;l<layers;l++) {
277 root 1.2 if(options & OPT_LINEAR) { /* linear door placement. */
278     switch(which_wall) {
279     case 1: { /* left hand wall */
280     x1 = (int)xlocations[l];
281     y1 = (int)( (ylocations[l] + ylocations[2*layers-l-1])/2);
282     break;
283     }
284     case 2: { /* top wall placement */
285     x1 = (int)( (xlocations[l] + xlocations[2*layers-l-1])/2);
286     y1 = (int)ylocations[l];
287     break;
288     }
289     case 3: { /* right wall placement */
290     x1 = (int)xlocations[2*layers-l-1];
291     y1 = (int)( (ylocations[l] + ylocations[2*layers-l-1])/2);
292     break;
293     }
294     case 4: { /* bottom wall placement */
295     x1 = (int)( (xlocations[l] + xlocations[2*layers-l-1])/2);
296     y1 = (int)ylocations[2*layers -l -1];
297     break;
298     }
299     }
300     }
301     else { /* random door placement. */
302     which_wall=RANDOM()%freedoms + 1;
303     switch(which_wall) {
304     case 1: { /* left hand wall */
305     x1 = (int)xlocations[l];
306     y2 = (int) (ylocations[2*layers-l-1]-ylocations[l]-1);
307     if(y2 > 0) y1 = (int) (ylocations[l]+RANDOM() %y2 + 1);
308     else y1 = (int) (ylocations[l]+1);
309     break;
310     }
311     case 2: { /* top wall placement */
312     x2 = (int)( (-xlocations[l] + xlocations[2*layers-l-1]))-1;
313     if (x2 > 0) x1 = (int) (xlocations[l]+RANDOM()%x2 + 1);
314     else x1 = (int) (xlocations[l]+1);
315     y1 = (int)ylocations[l];
316     break;
317     }
318     case 3: { /* right wall placement */
319     x1 = (int)xlocations[2*layers-l-1];
320     y2 = (int)( (-ylocations[l] + ylocations[2*layers-l-1]))-1;
321     if(y2 > 0) y1 = (int) (ylocations[l]+RANDOM() %y2 + 1);
322     else y1 = (int) (ylocations[l]+1);
323    
324     break;
325     }
326     case 4: { /* bottom wall placement */
327     x2 = (int)( (-xlocations[l] + xlocations[2*layers-l-1]))-1;
328     if (x2 > 0) x1 = (int) (xlocations[l]+RANDOM()%x2 + 1);
329     else x1 = (int) (xlocations[l]+1);
330     y1 = (int)ylocations[2*layers-l-1];
331     break;
332     }
333    
334     }
335     }
336     if(options & OPT_NO_DOORS)
337 elmex 1.1 maze[x1][y1] = '#'; /* no door. */
338     else
339     maze[x1][y1] = 'D'; /* write the door */
340    
341     }
342     /* mark the center of the maze with a C */
343     l = layers -1;
344     x1 = (int) (xlocations[l] + xlocations[2*layers -l -1])/2;
345     y1 = (int) (ylocations[l] + ylocations[2*layers -l -1])/2;
346     maze[x1][y1] = 'C';
347    
348     /* not needed anymore */
349     free(xlocations);
350     free(ylocations);
351    
352     }
353    
354     void bottom_right_centered_onion(char **maze, int xsize, int ysize, int option, int layers){
355     int i,maxlayers;
356     float *xlocations;
357     float *ylocations;
358    
359     maxlayers = (MIN(xsize,ysize)-2)/5;
360     if(!maxlayers) return; /* map too small to onionize */
361     if(layers > maxlayers) layers = maxlayers;
362     if(layers == 0) layers = (RANDOM() % maxlayers)+1;
363     xlocations = (float *) calloc(sizeof(float),2 * layers);
364     ylocations = (float *) calloc(sizeof(float),2 * layers);
365    
366    
367     /* place all the walls */
368     if(option & OPT_IRR_SPACE) /* randomly spaced */ {
369 root 1.2 int x_spaces_available, y_spaces_available;
370     /* the "extra" spaces available for spacing between layers */
371     x_spaces_available = (xsize -2) - 3*layers +1;
372     y_spaces_available = (ysize -2) - 3*layers +1;
373    
374    
375     /* pick an initial random pitch */
376     for(i=0;i<2*layers;i++) {
377     float xpitch=2,ypitch=2;
378     if(x_spaces_available>0)
379     xpitch = 2 + (RANDOM()%x_spaces_available +
380     RANDOM()%x_spaces_available +
381     RANDOM()%x_spaces_available)/3;
382    
383     if(y_spaces_available>0)
384     ypitch = 2 + (RANDOM()%y_spaces_available +
385     RANDOM()%y_spaces_available +
386     RANDOM()%y_spaces_available)/3;
387     if(i < layers) xlocations[i] = ( (i>0)?xlocations[i-1]:0) + xpitch;
388     else xlocations[i] = xsize-1;
389    
390     if(i < layers) ylocations[i] = ( (i>0)?ylocations[i-1]:0) + ypitch;
391     else ylocations[i] = ysize-1;
392     x_spaces_available-=(int)(xpitch -2);
393     y_spaces_available-=(int)(ypitch -2);
394     }
395    
396 elmex 1.1 }
397     if(!(option&OPT_IRR_SPACE)){ /* evenly spaced */
398     float xpitch, ypitch; /* pitch of the onion layers */
399     xpitch = (xsize-2.0)/(2.0*layers+1);
400     ypitch = (ysize-2.0)/(layers+1);
401     xlocations[0] = xpitch;
402     ylocations[0] = ypitch;
403     for(i=1;i<2*layers;i++) {
404 root 1.2 if(i < layers) xlocations[i] = xlocations[i-1] + xpitch;
405     else xlocations[i]=xsize-1;
406     if(i < layers) ylocations[i] = ylocations[i-1] + ypitch;
407     else ylocations[i]=ysize-1;
408 elmex 1.1 }
409     }
410    
411     /* draw all the onion boxes. */
412    
413     draw_onion(maze,xlocations,ylocations,layers);
414     make_doors(maze,xlocations,ylocations,layers,option);
415    
416     }