ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/room_gen_onion.C
Revision: 1.11
Committed: Sun Jul 1 05:00:19 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.10: +10 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.11 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.8 *
4 root 1.11 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.8 *
8 root 1.11 * Crossfire TRT is free software: you can redistribute it and/or modify
9 pippijn 1.8 * it under the terms of the GNU General Public License as published by
10 root 1.11 * the Free Software Foundation, either version 3 of the License, or
11 pippijn 1.8 * (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 root 1.11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 pippijn 1.8 * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19 root 1.11 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20     *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.8 */
23 elmex 1.1
24     /* The onion room generator:
25     Onion rooms are like this:
26    
27     char **map_gen_onion(int xsize, int ysize, int option, int layers);
28    
29     like this:
30     regular random
31     centered, linear onion bottom/right centered, nonlinear
32    
33     ######################### #########################
34     # # # #
35     # ######## ########## # # #####################
36     # # # # # # #
37     # # ###### ######## # # # # #
38     # # # # # # # # ######## ########
39     # # # #### ###### # # # # # # #
40     # # # # # # # # # # # #
41     # # # ############ # # # # # # ########### ##
42     # # # # # # # # # # #
43     # # ################ # # # # # # #########
44     # # # # # # # # #
45     # #################### # # # # # #
46     # # # # # # # #
47     ######################### #########################
48    
49     */
50    
51    
52     #include <global.h>
53     #include <random_map.h>
54    
55     #ifndef MIN
56 root 1.3 # define MIN(x,y) (((x)<(y))? (x):(y))
57 elmex 1.1 #endif
58 root 1.3 void centered_onion (char **maze, int xsize, int ysize, int option, int layers);
59     void bottom_centered_onion (char **maze, int xsize, int ysize, int option, int layers);
60     void bottom_right_centered_onion (char **maze, int xsize, int ysize, int option, int layers);
61 elmex 1.1
62    
63 root 1.3 void draw_onion (char **maze, float *xlocations, float *ylocations, int layers);
64     void make_doors (char **maze, float *xlocations, float *ylocations, int layers, int options);
65    
66     char **
67     map_gen_onion (int xsize, int ysize, int option, int layers)
68     {
69     int i, j;
70 elmex 1.1
71 root 1.3 /* allocate that array, set it up */
72     char **maze = (char **) calloc (sizeof (char *), xsize);
73 elmex 1.1
74 root 1.3 for (i = 0; i < xsize; i++)
75     {
76     maze[i] = (char *) calloc (sizeof (char), ysize);
77     }
78 elmex 1.1
79     /* pick some random options if option = 0 */
80 root 1.3 if (option == 0)
81     {
82 root 1.9 switch (rndm (3))
83 root 1.3 {
84 root 1.6 case 0:
85     option |= RMOPT_CENTERED;
86     break;
87     case 1:
88     option |= RMOPT_BOTTOM_C;
89     break;
90     case 2:
91     option |= RMOPT_BOTTOM_R;
92     break;
93 root 1.3 }
94 root 1.9 if (rndm (2))
95 root 1.5 option |= RMOPT_LINEAR;
96 root 1.9 if (rndm (2))
97 root 1.5 option |= RMOPT_IRR_SPACE;
98 root 1.3 }
99    
100 elmex 1.1 /* write the outer walls, if appropriate. */
101 root 1.5 if (!(option & RMOPT_WALL_OFF))
102 root 1.3 {
103     for (i = 0; i < xsize; i++)
104     maze[i][0] = maze[i][ysize - 1] = '#';
105     for (j = 0; j < ysize; j++)
106     maze[0][j] = maze[xsize - 1][j] = '#';
107     };
108 elmex 1.1
109 root 1.5 if (option & RMOPT_WALLS_ONLY)
110 root 1.3 return maze;
111 elmex 1.1
112     /* pick off the mutually exclusive options */
113 root 1.5 if (option & RMOPT_BOTTOM_R)
114 root 1.3 bottom_right_centered_onion (maze, xsize, ysize, option, layers);
115 root 1.5 else if (option & RMOPT_BOTTOM_C)
116 root 1.3 bottom_centered_onion (maze, xsize, ysize, option, layers);
117 root 1.5 else if (option & RMOPT_CENTERED)
118 root 1.3 centered_onion (maze, xsize, ysize, option, layers);
119    
120 elmex 1.1 return maze;
121     }
122    
123 root 1.3 void
124     centered_onion (char **maze, int xsize, int ysize, int option, int layers)
125     {
126     int i, maxlayers;
127 elmex 1.1 float *xlocations;
128     float *ylocations;
129    
130 root 1.3 maxlayers = (MIN (xsize, ysize) - 2) / 5;
131     if (!maxlayers)
132     return; /* map too small to onionize */
133 root 1.10
134 root 1.3 if (layers > maxlayers)
135     layers = maxlayers;
136 root 1.10
137 root 1.3 if (layers == 0)
138 root 1.10 layers = rndm (maxlayers) + 1;
139    
140 root 1.3 xlocations = (float *) calloc (sizeof (float), 2 * layers);
141     ylocations = (float *) calloc (sizeof (float), 2 * layers);
142    
143 elmex 1.1 /* place all the walls */
144 root 1.6 if (option & RMOPT_IRR_SPACE) /* randomly spaced */
145 root 1.3 {
146     int x_spaces_available, y_spaces_available;
147    
148     /* the "extra" spaces available for spacing between layers */
149     x_spaces_available = (xsize - 2) - 6 * layers + 1;
150     y_spaces_available = (ysize - 2) - 6 * layers + 1;
151    
152    
153     /* pick an initial random pitch */
154     for (i = 0; i < 2 * layers; i++)
155     {
156     float xpitch = 2, ypitch = 2;
157    
158     if (x_spaces_available > 0)
159 root 1.10 xpitch = 2 + (rndm (x_spaces_available) + rndm (x_spaces_available) + rndm (x_spaces_available)) / 3;
160 root 1.3
161     if (y_spaces_available > 0)
162 root 1.10 ypitch = 2 + (rndm (y_spaces_available) + rndm (y_spaces_available) + rndm (y_spaces_available)) / 3;
163    
164 root 1.3 xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch;
165     ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch;
166     x_spaces_available -= (int) (xpitch - 2);
167     y_spaces_available -= (int) (ypitch - 2);
168     }
169    
170     }
171 root 1.5 if (!(option & RMOPT_IRR_SPACE))
172 root 1.3 { /* evenly spaced */
173     float xpitch, ypitch; /* pitch of the onion layers */
174    
175     xpitch = (xsize - 2.0) / (2.0 * layers + 1);
176     ypitch = (ysize - 2.0) / (2.0 * layers + 1);
177     xlocations[0] = xpitch;
178     ylocations[0] = ypitch;
179     for (i = 1; i < 2 * layers; i++)
180     {
181     xlocations[i] = xlocations[i - 1] + xpitch;
182     ylocations[i] = ylocations[i - 1] + ypitch;
183     }
184 elmex 1.1 }
185 root 1.3
186 elmex 1.1 /* draw all the onion boxes. */
187    
188 root 1.3 draw_onion (maze, xlocations, ylocations, layers);
189     make_doors (maze, xlocations, ylocations, layers, option);
190    
191 elmex 1.1 }
192    
193 root 1.3 void
194     bottom_centered_onion (char **maze, int xsize, int ysize, int option, int layers)
195     {
196     int i, maxlayers;
197 elmex 1.1 float *xlocations;
198     float *ylocations;
199    
200 root 1.3 maxlayers = (MIN (xsize, ysize) - 2) / 5;
201     if (!maxlayers)
202     return; /* map too small to onionize */
203     if (layers > maxlayers)
204     layers = maxlayers;
205     if (layers == 0)
206 root 1.10 layers = rndm (maxlayers) + 1;
207 root 1.3 xlocations = (float *) calloc (sizeof (float), 2 * layers);
208     ylocations = (float *) calloc (sizeof (float), 2 * layers);
209    
210    
211 elmex 1.1 /* place all the walls */
212 root 1.6 if (option & RMOPT_IRR_SPACE) /* randomly spaced */
213 root 1.3 {
214     int x_spaces_available, y_spaces_available;
215    
216     /* the "extra" spaces available for spacing between layers */
217     x_spaces_available = (xsize - 2) - 6 * layers + 1;
218     y_spaces_available = (ysize - 2) - 3 * layers + 1;
219    
220    
221     /* pick an initial random pitch */
222     for (i = 0; i < 2 * layers; i++)
223     {
224     float xpitch = 2, ypitch = 2;
225    
226     if (x_spaces_available > 0)
227 root 1.10 xpitch = 2 + (rndm (x_spaces_available) + rndm (x_spaces_available) + rndm (x_spaces_available)) / 3;
228 root 1.3
229     if (y_spaces_available > 0)
230 root 1.10 ypitch = 2 + (rndm (y_spaces_available) + rndm (y_spaces_available) + rndm (y_spaces_available)) / 3;
231    
232 root 1.3 xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch;
233     if (i < layers)
234     ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch;
235     else
236     ylocations[i] = ysize - 1;
237 root 1.10
238 root 1.3 x_spaces_available -= (int) (xpitch - 2);
239     y_spaces_available -= (int) (ypitch - 2);
240     }
241    
242 elmex 1.1 }
243 root 1.5 if (!(option & RMOPT_IRR_SPACE))
244 root 1.3 { /* evenly spaced */
245     float xpitch, ypitch; /* pitch of the onion layers */
246    
247     xpitch = (xsize - 2.0) / (2.0 * layers + 1);
248     ypitch = (ysize - 2.0) / (layers + 1);
249     xlocations[0] = xpitch;
250     ylocations[0] = ypitch;
251     for (i = 1; i < 2 * layers; i++)
252     {
253     xlocations[i] = xlocations[i - 1] + xpitch;
254     if (i < layers)
255     ylocations[i] = ylocations[i - 1] + ypitch;
256     else
257     ylocations[i] = ysize - 1;
258     }
259     }
260    
261 elmex 1.1 /* draw all the onion boxes. */
262    
263 root 1.3 draw_onion (maze, xlocations, ylocations, layers);
264     make_doors (maze, xlocations, ylocations, layers, option);
265    
266 elmex 1.1 }
267    
268    
269     /* draw_boxes: draws the lines in the maze defining the onion layers */
270    
271 root 1.3 void
272     draw_onion (char **maze, float *xlocations, float *ylocations, int layers)
273     {
274     int i, j, l;
275    
276     for (l = 0; l < layers; l++)
277     {
278     int x1, x2, y1, y2;
279    
280     /* horizontal segments */
281     y1 = (int) ylocations[l];
282     y2 = (int) ylocations[2 * layers - l - 1];
283     for (i = (int) xlocations[l]; i <= (int) xlocations[2 * layers - l - 1]; i++)
284     {
285     maze[i][y1] = '#';
286     maze[i][y2] = '#';
287     }
288    
289     /* vertical segments */
290     x1 = (int) xlocations[l];
291     x2 = (int) xlocations[2 * layers - l - 1];
292     for (j = (int) ylocations[l]; j <= (int) ylocations[2 * layers - l - 1]; j++)
293     {
294     maze[x1][j] = '#';
295     maze[x2][j] = '#';
296     }
297 elmex 1.1
298 root 1.3 }
299 elmex 1.1 }
300    
301 root 1.3 void
302     make_doors (char **maze, float *xlocations, float *ylocations, int layers, int options)
303     {
304     int freedoms; /* number of different walls on which we could place a door */
305     int which_wall; /* left, 1, top, 2, right, 3, bottom 4 */
306     int l, x1 = 0, x2, y1 = 0, y2;
307    
308     freedoms = 4; /* centered */
309 root 1.5 if (options & RMOPT_BOTTOM_C)
310 root 1.3 freedoms = 3;
311 root 1.5 if (options & RMOPT_BOTTOM_R)
312 root 1.3 freedoms = 2;
313     if (layers <= 0)
314     return;
315 root 1.10
316 elmex 1.1 /* pick which wall will have a door. */
317 root 1.10 which_wall = rndm (freedoms) + 1;
318 root 1.3 for (l = 0; l < layers; l++)
319     {
320 root 1.5 if (options & RMOPT_LINEAR)
321 root 1.3 { /* linear door placement. */
322     switch (which_wall)
323     {
324 root 1.6 case 1:
325     { /* left hand wall */
326     x1 = (int) xlocations[l];
327     y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2);
328     break;
329     }
330     case 2:
331     { /* top wall placement */
332     x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2);
333     y1 = (int) ylocations[l];
334     break;
335     }
336     case 3:
337     { /* right wall placement */
338     x1 = (int) xlocations[2 * layers - l - 1];
339     y1 = (int) ((ylocations[l] + ylocations[2 * layers - l - 1]) / 2);
340     break;
341     }
342     case 4:
343     { /* bottom wall placement */
344     x1 = (int) ((xlocations[l] + xlocations[2 * layers - l - 1]) / 2);
345     y1 = (int) ylocations[2 * layers - l - 1];
346     break;
347     }
348 root 1.3 }
349     }
350     else
351     { /* random door placement. */
352 root 1.10 which_wall = rndm (freedoms) + 1;
353 root 1.3 switch (which_wall)
354     {
355 root 1.6 case 1:
356     { /* left hand wall */
357     x1 = (int) xlocations[l];
358     y2 = (int) (ylocations[2 * layers - l - 1] - ylocations[l] - 1);
359     if (y2 > 0)
360 root 1.10 y1 = (int) (ylocations[l] + rndm (y2) + 1);
361 root 1.6 else
362     y1 = (int) (ylocations[l] + 1);
363     break;
364     }
365     case 2:
366     { /* top wall placement */
367     x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1;
368     if (x2 > 0)
369 root 1.10 x1 = (int) (xlocations[l] + rndm (x2) + 1);
370 root 1.6 else
371     x1 = (int) (xlocations[l] + 1);
372     y1 = (int) ylocations[l];
373     break;
374     }
375     case 3:
376     { /* right wall placement */
377     x1 = (int) xlocations[2 * layers - l - 1];
378     y2 = (int) ((-ylocations[l] + ylocations[2 * layers - l - 1])) - 1;
379     if (y2 > 0)
380 root 1.10 y1 = (int) (ylocations[l] + rndm (y2) + 1);
381 root 1.6 else
382     y1 = (int) (ylocations[l] + 1);
383    
384     break;
385     }
386     case 4:
387     { /* bottom wall placement */
388     x2 = (int) ((-xlocations[l] + xlocations[2 * layers - l - 1])) - 1;
389     if (x2 > 0)
390 root 1.10 x1 = (int) (xlocations[l] + rndm (x2) + 1);
391 root 1.6 else
392     x1 = (int) (xlocations[l] + 1);
393     y1 = (int) ylocations[2 * layers - l - 1];
394     break;
395     }
396 root 1.3
397     }
398     }
399 root 1.5 if (options & RMOPT_NO_DOORS)
400 root 1.3 maze[x1][y1] = '#'; /* no door. */
401     else
402     maze[x1][y1] = 'D'; /* write the door */
403 elmex 1.1
404 root 1.3 }
405 elmex 1.1 /* mark the center of the maze with a C */
406 root 1.3 l = layers - 1;
407     x1 = (int) (xlocations[l] + xlocations[2 * layers - l - 1]) / 2;
408     y1 = (int) (ylocations[l] + ylocations[2 * layers - l - 1]) / 2;
409 elmex 1.1 maze[x1][y1] = 'C';
410    
411     /* not needed anymore */
412 root 1.3 free (xlocations);
413     free (ylocations);
414    
415 elmex 1.1 }
416    
417 root 1.3 void
418     bottom_right_centered_onion (char **maze, int xsize, int ysize, int option, int layers)
419     {
420     int i, maxlayers;
421 elmex 1.1 float *xlocations;
422     float *ylocations;
423    
424 root 1.3 maxlayers = (MIN (xsize, ysize) - 2) / 5;
425     if (!maxlayers)
426     return; /* map too small to onionize */
427     if (layers > maxlayers)
428     layers = maxlayers;
429     if (layers == 0)
430 root 1.10 layers = rndm (maxlayers) + 1;
431    
432 root 1.3 xlocations = (float *) calloc (sizeof (float), 2 * layers);
433     ylocations = (float *) calloc (sizeof (float), 2 * layers);
434    
435 elmex 1.1 /* place all the walls */
436 root 1.6 if (option & RMOPT_IRR_SPACE) /* randomly spaced */
437 root 1.3 {
438     int x_spaces_available, y_spaces_available;
439    
440     /* the "extra" spaces available for spacing between layers */
441     x_spaces_available = (xsize - 2) - 3 * layers + 1;
442     y_spaces_available = (ysize - 2) - 3 * layers + 1;
443    
444    
445     /* pick an initial random pitch */
446     for (i = 0; i < 2 * layers; i++)
447     {
448     float xpitch = 2, ypitch = 2;
449    
450     if (x_spaces_available > 0)
451 root 1.10 xpitch = 2 + (rndm (x_spaces_available) + rndm (x_spaces_available) + rndm (x_spaces_available)) / 3;
452 root 1.3
453     if (y_spaces_available > 0)
454 root 1.10 ypitch = 2 + (rndm (y_spaces_available) + rndm (y_spaces_available) + rndm (y_spaces_available)) / 3;
455    
456 root 1.3 if (i < layers)
457     xlocations[i] = ((i > 0) ? xlocations[i - 1] : 0) + xpitch;
458     else
459     xlocations[i] = xsize - 1;
460    
461     if (i < layers)
462     ylocations[i] = ((i > 0) ? ylocations[i - 1] : 0) + ypitch;
463     else
464     ylocations[i] = ysize - 1;
465     x_spaces_available -= (int) (xpitch - 2);
466     y_spaces_available -= (int) (ypitch - 2);
467     }
468    
469 elmex 1.1 }
470 root 1.5 if (!(option & RMOPT_IRR_SPACE))
471 root 1.3 { /* evenly spaced */
472     float xpitch, ypitch; /* pitch of the onion layers */
473    
474     xpitch = (xsize - 2.0) / (2.0 * layers + 1);
475     ypitch = (ysize - 2.0) / (layers + 1);
476     xlocations[0] = xpitch;
477     ylocations[0] = ypitch;
478     for (i = 1; i < 2 * layers; i++)
479     {
480     if (i < layers)
481     xlocations[i] = xlocations[i - 1] + xpitch;
482     else
483     xlocations[i] = xsize - 1;
484     if (i < layers)
485     ylocations[i] = ylocations[i - 1] + ypitch;
486     else
487     ylocations[i] = ysize - 1;
488     }
489     }
490    
491 elmex 1.1 /* draw all the onion boxes. */
492    
493 root 1.3 draw_onion (maze, xlocations, ylocations, layers);
494     make_doors (maze, xlocations, ylocations, layers, option);
495    
496 elmex 1.1 }