ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cf.schmorp.de/maps/Info/land.c
Revision: 1.1.1.1 (vendor branch)
Committed: Sat Feb 4 23:56:12 2006 UTC (18 years, 10 months ago) by root
Content type: text/plain
Branch: UPSTREAM, MAIN
CVS Tags: post_fixaltar, last_stable, post_fixaltar2, rel-2_82, rel-2_81, rel-2_80, pre_coinconvert, UPSTREAM_2006_03_15, rel-3_0, rel-2_6, rel-2_7, rel-2_4, rel-2_5, rel-2_2, rel-2_0, rel-2_1, rel-2_72, rel-2_73, rel-2_71, rel-2_76, rel-2_77, rel-2_74, rel-2_75, rel-2_54, rel-2_55, rel-2_56, rel-2_79, UPSTREAM_2006_02_01, rel-2_53, pre_material_cfarch_normalize_run, rel-2_32, pre_fixconverter, post_coinconvert, pre_fixaltar2, pre_map_rename, UPSTREAM_2006_02_22, rel-2_90, rel-2_92, rel-2_93, rel-2_78, post_fixconverter, pre_fixaltar, rel-2_61, rel-2_43, rel-2_42, rel-2_41, HEAD
Changes since 1.1: +0 -0 lines
Log Message:
Initial Import

File Contents

# User Rev Content
1 root 1.1 #include <stdio.h>
2     #include <stdlib.h>
3    
4     #define MAX_SIZE 3000
5     #define MAX(x,y) ((x)>(y)?(x):(y))
6    
7     #define BASE_ALT -100
8    
9     /* make this a global to avoid stack overflow */
10     int altitude[MAX_SIZE][MAX_SIZE];
11    
12     /* This function writes out the crossfire maps. So shoot me for
13     * using compiled in constants - I'm not going to use this so much
14     * that I wanted to do anything too easy.
15     */
16    
17     #define MAP_FORMAT "world_%03d_%03d"
18    
19     /* Maps are square */
20    
21     #define MAP_SIZE 50
22    
23     /* There will be a total of 2500 maps (eek) - 50 in
24     * each diretion. STARTX and STARTY are where to start
25     * numbering from. I chose 100 for a few reasons - 1) it
26     * gives room to the left and above to add some things (another
27     * continent for that matter), and 2) since the format allows
28     * for up to 1000 in each direction, this seemed reasonable.
29     * Note - if you do the math, and have 1000 * 1000 maps, each
30     * with 50*50 spaces, you have a total of 2.5 billion spaces.
31     * So hopefully that should be large enough.
32     */
33    
34     #define STARTX 100
35     #define STARTY 100
36    
37     typedef enum {
38     None=0,
39     DeepWater=1,
40     MediumWater=2,
41     ShallowWater=3,
42     Swamp=4,
43     DeepSwamp=5,
44     Grass=6,
45     Desert=7,
46     Brush=8,
47     EverGreens=9,
48     Jungle=10,
49     Tree1=11,
50     Tree2=12,
51     Woods1=13,
52     Woods2=14,
53     Woods3=15,
54     Hills=16,
55     HillsRocky=17,
56     Steppe=17,
57     Mountain=19,
58     HighMountain=20,
59     WasteLand=21
60     } Terrain_Types;
61    
62     char *Terrain_Names[][2] = {
63     /* these are the archetype names. They are in the same order
64     * as the Terrain_Types above. Note many terrain types are not
65     * included because handling them would be too difficult.
66     */
67     {"None", "0, 0, 0 "},
68     {"deep_sea", "0 0 127 "},
69     {"sea", "0 0 192 "},
70     {"shallow_sea", "0 0 255 "}, /* wading depth */
71     {"swamp", "12 161 64 "},
72     {"deep_swamp", "155 175 164 "},
73     {"grass", "0 255 0 "},
74     {"desert", "222 218 135 "},
75     {"brush", "1 144 1 "},
76     {"evergreens", "0 128 0 "},
77     {"jungle_1", "0 176 0 "},
78     {"tree", "4 133 01 "},
79     {"evergreen", "20 209 0 "},
80     {"woods", "4 115 01 "},
81     {"woods_2", "1 182 02 "},
82     {"woods_3", "4 153 02 "},
83     {"hills", "166 160 70 "},
84     {"hills_rocky", "166 155 70 "},
85     {"steppe", "150 97 34 "},
86     {"mountain", "183 190 190 "},
87     {"mountain2", "191 196 185 "},
88     {"wasteland", "255 255 255 "},
89     };
90    
91    
92    
93     void write_crossfire_maps(int mapx, int mapy)
94     {
95     int x, y,n,q, nx, ny,r1,r2,ax=0,ay=0, j, k;
96     char name[512];
97     FILE *fp;
98     Terrain_Types *terrain;
99    
100     terrain = calloc(mapx * mapy * sizeof(Terrain_Types), sizeof(Terrain_Types));
101    
102     /* First fill in the water and the highest of peaks */
103     for (x=0; x<mapx; x++) {
104     for (y=0; y<mapy; y++) {
105     if (altitude[y][x] < -5000) {
106     terrain[x + y * mapx] = DeepWater;
107     } else if (altitude[y][x] < -99) {
108     terrain[x + y * mapx] = MediumWater;
109     } else if (altitude[y][x] < 1) {
110     terrain[x + y * mapx] = ShallowWater;
111     } else if (altitude[y][x] >=12000) {
112     /* Not really precisely wasteland, but wastelands are impassable */
113     terrain[x + y * mapx] = WasteLand;
114     }
115     }
116     }
117     /* Basically, take a random bit and populate the area with terrain.
118     * We do this so it won't be totally monolythic (have several forest types
119     * for example), yet patches will be the same thing, eg, a stretch of
120     * desert, which wouldn't work very well if we just chose randomly
121     * for each space.
122     */
123    
124     for (n=0; n<(mapx * mapy) / 100; n++) {
125     do {
126     x = random() % mapx;
127     y = random() % mapy;
128     } while ( terrain[x + y * mapx] == None);
129    
130     nx = x + 40;
131     if (nx > mapx) nx=mapx;
132     ny = y + 40;
133     if (ny > mapy) ny = mapy;
134     r1 = random();
135     r2 = random();
136     for (x = nx-40; x<nx; x++) {
137     for (y=ny-40; y<ny; y++) {
138     if (terrain[x + y * mapx] != None) continue;
139    
140     /* near the edges, don't always fill in so that hopefully something
141     * else will fill in and smooth these out some
142     */
143     if ( (x < (nx -30) || y < (ny - 30) || x > (nx -10) || y > (ny - 10)) &&
144     random() % 2) continue;
145    
146     if (altitude[y][x] < 10) {
147     terrain[x + y * mapx] = Swamp + (r1 % 2);
148     }
149     else if (altitude[y][x] < 1000) {
150     terrain[x + y * mapx] = Grass + (r1 % 3);
151     } else if (altitude[y][x] < 3000) {
152     terrain[x + y * mapx] = EverGreens + (r1 % 9);
153     } else if (altitude[y][x] < 5000) {
154     terrain[x + y * mapx] = Hills + (r2 % 3);
155     } else if (altitude[y][x] < 9000) {
156     terrain[x + y * mapx] = Mountain;
157     } else if (altitude[y][x] < 12000) {
158     terrain[x + y * mapx] = HighMountain;
159     }
160     else fprintf(stderr,"altitude %d did not get filled in?\n", altitude[y][x]);
161     }
162     }
163     }
164     /* Now just fill in the spaces randomly. */
165     n=0;
166     r1 = random();
167     r2 = random();
168     for (x=0; x<mapx; x++) {
169     for (y=0; y<mapy; y++) {
170     if (terrain[x + y * mapx] != None) continue;
171     n++;
172     if (altitude[y][x] < 10) {
173     terrain[x + y * mapx] = Swamp + (r1 % 2);
174     }
175     if (altitude[y][x] < 1000) {
176     terrain[x + y * mapx] = Grass + (r1 % 3);
177     } else if (altitude[y][x] < 3000) {
178     terrain[x + y * mapx] = EverGreens + (r2 % 9);
179     } else if (altitude[y][x] < 5000) {
180     terrain[x + y * mapx] = Hills + (r2 % 3);
181     } else if (altitude[y][x] < 9000) {
182     terrain[x + y * mapx] = Mountain;
183     } else if (altitude[y][x] < 12000) {
184     terrain[x + y * mapx] = HighMountain;
185     }
186     }
187     }
188     fprintf(stderr,"Filled in %d spaces\n",n);
189     if ((mapx / MAP_SIZE) * MAP_SIZE != mapx ||
190     (mapy / MAP_SIZE) * MAP_SIZE != mapy) {
191     fprintf(stderr,"Warning - generated map does not evenly tile.\n");
192     }
193     for (nx= STARTX; nx<(STARTX + (mapx/ MAP_SIZE)); nx++) {
194     for (ny= STARTY; ny<(STARTY + (mapy/ MAP_SIZE)); ny++) {
195     ax = (nx - STARTX) * MAP_SIZE;
196     ay = (ny - STARTY) * MAP_SIZE;
197    
198     sprintf(name,MAP_FORMAT,nx,ny);
199     if ((fp=fopen(name, "w"))==NULL) {
200     fprintf(stderr,"unable to open %s\n", name);
201     }
202     /* Write the header for the map */
203     fprintf(fp,"arch map\n");
204     fprintf(fp,"name %s\n", name);
205     fprintf(fp,"width %d\n", MAP_SIZE);
206     fprintf(fp,"height %d\n", MAP_SIZE);
207     /* Not used right now, but useful to include */
208     fprintf(fp,"outdoor 1\n", MAP_SIZE);
209    
210     /* don't do difficult, reset time, or enter coordinates */
211     /* Set up the tile paths */
212     if (ny != STARTY) {
213     fprintf(fp,"tile_path_1 ");
214     fprintf(fp,MAP_FORMAT,nx, ny-1);
215     fprintf(fp,"\n");
216     }
217     if ((nx+1) < STARTX + (mapx/ MAP_SIZE)) {
218     fprintf(fp,"tile_path_2 ");
219     fprintf(fp,MAP_FORMAT,nx+1, ny);
220     fprintf(fp,"\n");
221     }
222     if ((ny+1) < STARTY + (mapy/ MAP_SIZE)) {
223     fprintf(fp,"tile_path_3 ");
224     fprintf(fp,MAP_FORMAT,nx, ny+1);
225     fprintf(fp,"\n");
226     }
227     if (nx != STARTX) {
228     fprintf(fp,"tile_path_4 ");
229     fprintf(fp,MAP_FORMAT,nx-1, ny);
230     fprintf(fp,"\n");
231     }
232     fprintf(fp,"end\n");
233     for (x = 0; x<50; x++) {
234     for (y = 0; y < 50; y++) {
235     q = terrain[x + ax + (y + ay)* mapx];
236     fprintf(fp, "arch %s\n",Terrain_Names[q][0]);
237     fprintf(fp,"x %d\n", x);
238     fprintf(fp,"y %d\n", y);
239     q = altitude[y + ay ][x + ax];
240     if (q< -32000) q = -32000;
241     if (q > 32000) q = 32000;
242     fprintf(fp,"elevation %d\n", q);
243     fprintf(fp,"end\n");
244     }
245     }
246     fclose(fp);
247     }
248     }
249    
250     fp = fopen("cmap", "w");
251     fprintf(fp, "P3 %d %d 255\n", mapy, mapx);
252     for (y=0; y < mapy; y++) {
253     for (x=0; x < mapx; x++) {
254     fprintf(fp, Terrain_Names[terrain[x + y * mapx]][1]);
255     }
256     fprintf(fp, "\n");
257     }
258     exit(0);
259     }
260    
261    
262    
263     main(int argc, char *argv)
264     {
265     int x, y, max_x=500, max_y=500, seed, land=300000, npasses=40, newalt, wpasses=50, water=50000;
266     int n, i, j, k, l, z, w, r, a, write_maps=0;
267     FILE *fp, *lp;
268     int junk;
269     char c;
270     extern char *optarg;
271    
272     seed = time(NULL);
273     while ((c = getopt(argc, argv,"x:y:s:l:n:w:p:m"))!=-1) {
274     switch (c) {
275     case 'l':
276     land = atoi(optarg);
277     if (land < 11 ) {
278     fprintf(stderr,"-l must be at least 11\n");
279     exit(1);
280     }
281     break;
282    
283     case 'w':
284     water = atoi(optarg);
285     if (water < 1 ) {
286     fprintf(stderr,"-w must be at least 1\n");
287     exit(1);
288     }
289     break;
290    
291     case 'p':
292     wpasses = atoi(optarg);
293     if (wpasses < 1 ) {
294     fprintf(stderr,"-w must be at least 1\n");
295     exit(1);
296     }
297     break;
298    
299     case 'n':
300     npasses = atoi(optarg);
301     if (npasses < 10 ) {
302     fprintf(stderr,"-n must be at least 10\n");
303     exit(1);
304     }
305     break;
306    
307     case 'x':
308     max_x = atoi(optarg);
309     break;
310    
311     case 'y':
312     max_y = atoi(optarg);
313     break;
314    
315     case 's':
316     seed = atoi(optarg);
317     break;
318    
319     case 'm':
320     write_maps=1;
321     break;
322     }
323     }
324     if (max_x > MAX_SIZE || max_y > MAX_SIZE) {
325     fprintf(stderr,"Max X and Y size is %d\n", MAX_SIZE);
326     exit(1);
327     }
328    
329     fprintf(stderr,"Making %d X %d map, seed %d, land %d, passes = %d\n", max_x, max_y, seed, land, npasses);
330     fprintf(stderr,"wpasses =%d, water=%d\n", wpasses, water);
331     fprintf(stderr,"-x %d -y %d -s %d -p %d -n %d -w %d -l %d\n",
332     max_x, max_y, seed, wpasses, npasses, water, land);
333    
334     srandom(seed);
335    
336     for (x=20; x < max_x-20; x++)
337     for (y=20; y < max_y-20; y++)
338     altitude[x][y] = BASE_ALT;
339    
340     for (x=0; x<max_x; x++) {
341     for (y=0; y<20; y++) {
342     altitude[x][y] = (y -20 ) * 100;
343     altitude[x][max_y - y] = (y -20 ) * 100;
344     }
345     }
346    
347     for (y=10; y<max_y-10; y++) {
348     for (x=0; x<20; x++) {
349     altitude[x][y] = (x - 20) * 100;
350     altitude[max_x - x][y] = (x - 20) * 100;
351     }
352     }
353    
354     /* This basically produces areas of high varience (eg, islands, peaks, valleys, etc) */
355    
356     for (l=0; l<npasses; l++) {
357     x = random()%max_x;
358     y = random()%max_y;
359     /* Weigh our selected starting position a little more towards the center
360     * so the continent is more in the center
361     */
362     if (random() % 2) {
363     x += random()%max_x;
364     y += random()%max_y;
365     x /=2;
366     y /=2;
367     }
368     n = random()%500+800;
369    
370     /* For some portion, try to find a pixel we have yet to modify */
371     if (l> (npasses * 15) / 20) {
372     int tries=0;
373     while (altitude[x][y] == BASE_ALT) {
374     x = random()%max_x;
375     y = random()%max_y;
376     if (random() % 2) {
377     x += random()%max_x;
378     y += random()%max_y;
379     x /=2;
380     y /=2;
381     }
382     tries++;
383     if (tries > 50) {
384     fprintf(stderr,"did not find free space within %d tries\n", tries);
385     break;
386     }
387     }
388    
389     }
390    
391     for (k=1; k< land ; k++) {
392     r = random()%4;
393     switch (r) {
394     case 0: if (x<max_x-1) x++; else x -= random() % (max_x/2); break;
395     case 1: if (y<max_y-1) y++; else y -= random() % (max_y/2); break;
396     case 2: if (x) x--; else x+= random() % (max_x/2); break;
397     case 3: if (y) y--; else y+= random() % (max_y/2); break;
398     }
399     altitude[x][y] += n;
400     if (random()%k < 100)
401     n -= 1;
402     }
403     }
404    
405     /* Make lakes and ocean trenches.
406     * General note - it works better to have more passes, but each
407     * pass doing less working - this results in more consistent lakes
408     * and ocen trenching.
409     */
410     for (l=0; l<wpasses; l++) {
411     /* for a small portion, we lower the area we make */
412     n = random()%1500-2000;
413    
414     x = random()% max_x;
415     y = random()% max_y;
416    
417     while (altitude[x][y] > BASE_ALT || altitude[x][y]<-7000) {
418     x = random()% max_x;
419     y = random()% max_y;
420     }
421     for (k=1; k< water ; k++) {
422     r = random()%4;
423     switch (r) {
424     case 0: if (x<max_x-1) x++; break;
425     case 1: if (y<max_y-1) y++; break;
426     case 2: if (x) x--; break;
427     case 3: if (y) y--; break;
428     }
429     altitude[x][y] += n;
430     if (random()%k < 100)
431     n += 1; /*less dramatic as things go on */
432     }
433     }
434    
435    
436     /* This block seems to average out the spaces somewhat to prevent
437     * cliffs and the like.
438     */
439     #define NUM_PASSES 3
440     r = 10;
441     for (k=0; k<NUM_PASSES; k++) {
442     for (x=2; x<max_x-2; x++) {
443     for (y=2; y<max_y - 2; y++) {
444     newalt = (altitude[x][y] * r + altitude[x-1][y] +
445     altitude[x][y-1] + altitude[x-1][y-1] +
446     altitude[x+1][y] + altitude[x][y+1] +
447     altitude[x+1][y+1] + altitude[x+1][y-1] +
448     altitude[x-1][y+1]) / (r+8);
449     if (altitude[x][y] < 10 || altitude[x][y] > newalt) altitude[x][y] = newalt;
450     }
451     }
452     for (x=max_x-2; x>2; x--) {
453     for (y=max_y-2; y>2; y--) {
454     newalt = (altitude[x][y] * r + altitude[x-1][y] +
455     altitude[x][y-1] + altitude[x-1][y-1] +
456     altitude[x+1][y] + altitude[x][y+1] +
457     altitude[x+1][y+1] + altitude[x+1][y-1] +
458     altitude[x-1][y+1]) / (r+8);
459     if (altitude[x][y] < 10 || altitude[x][y] > newalt) altitude[x][y] = newalt;
460     }
461     }
462     }
463    
464     /* Make this 100 so that we eliminate/reduce the lakiness of
465     * the map that is otherwise generated - otherwise, the map
466     * looks like an archipelligo
467     */
468     #define AVG_PT -10
469    
470     /* water - does the same as above, but try to more equally balnace the spaces*/
471     r = 1;
472     for (k=0; k<40; k++) {
473     for (x=2; x<max_x-2; x++) {
474     for (y=2; y<max_y -2; y++) {
475     if (altitude[x][y] < AVG_PT)
476     altitude[x][y] = (altitude[x][y] * r + altitude[x-1][y] +
477     altitude[x][y-1] + altitude[x-1][y-1] +
478     altitude[x+1][y] + altitude[x][y+1] +
479     altitude[x+1][y+1] + altitude[x+1][y-1] +
480     altitude[x-1][y+1]) / (r+8);
481     }
482     }
483     for (x=max_x-2; x>2; x--) {
484     for (y=max_y-2; y>2; y--) {
485     if (altitude[x][y] < AVG_PT)
486     altitude[x][y] = (altitude[x][y] * r + altitude[x-1][y] +
487     altitude[x][y-1] + altitude[x-1][y-1] +
488     altitude[x+1][y] + altitude[x][y+1] +
489     altitude[x+1][y+1] + altitude[x+1][y-1] +
490     altitude[x-1][y+1]) / (r+8);
491     }
492     }
493     }
494     if (write_maps)
495     write_crossfire_maps(max_x, max_y);
496    
497     /* Now write the data out */
498    
499     fp = fopen("lmap", "w");
500     lp = fopen("pmap", "w");
501     fprintf(fp, "P3 %d %d 255\n", max_y, max_x);
502     for (j=0; j < max_x; j++) {
503     for (k=0; k < max_y; k++) {
504     junk = altitude[j][k];
505     fprintf(lp, "%d ", altitude[j][k]);
506     if (junk < -5000)
507     fprintf(fp, "0 0 127 ");
508     /* Shallow water should really be just at the coastal
509     * area, so put a big gap between shallow and deep.
510     * this also evens out the occurance of the different types
511     * to be more equal
512     */
513     else if (junk < -99)
514     fprintf(fp, "0 0 192 ");
515     else if (junk < 1)
516     fprintf(fp, "0 0 255 ");
517     else if (junk < 1000)
518     fprintf(fp, "0 240 0 ");
519     else if (junk < 2000)
520     fprintf(fp, "0 220 0 ");
521     else if (junk < 3000)
522     fprintf(fp, "0 200 0 ");
523     else if (junk < 4000)
524     fprintf(fp, "0 180 0 ");
525     else if (junk < 5000)
526     fprintf(fp, "0 160 0 ");
527     else if (junk < 6000)
528     fprintf(fp, "255 130 71 ");
529     else if (junk < 8000)
530     fprintf(fp, "238 121 66 ");
531     else if (junk < 10000)
532     fprintf(fp, "205 104 57 ");
533     else if (junk < 12000)
534     fprintf(fp, "139 71 38 ");
535     else
536     fprintf(fp, "255 255 255 ");
537     }
538     fprintf(fp, "\n");
539     }
540     exit(0);
541     }