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

# Content
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 }