1 /*
2 GL-117
3 Copyright 2001, 2002 Thomas A. Drexl aka heptargon
4
5 This file is part of GL-117.
6
7 GL-117 is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GL-117 is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GL-117; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /* This file includes a random landscape generator. */
23
24 #ifndef IS_LAND_H
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <math.h>
29 #include <string.h>
30
31 #include "land.h"
32 #include "mathtab.h"
33
34
35
36 /****************************************************************************
37 COMMON GLOBAL FUNCTIONS
38 ****************************************************************************/
39
getCoord(int a)40 int Landscape::getCoord (int a)
41 {
42 return (a & MAXX_MASK);
43 // return (a>=0)? a%MAXX : MAXX-a%MAXX; // more general version
44 }
45
46
47
48 /****************************************************************************
49 SMOOTING, CONVOLUTION, EROSION
50 ****************************************************************************/
51
52 // fast Gaussian convolution (smoothing terrain)
53 // H := height matrix, K := Gaussian kernel matrix
54 // Let K := u conv v := (u^T)v, then H conv K = H conv (u conv v) = (H conv u) conv v
convolveGauss(int radius,int hmin,int hmax)55 void Landscape::convolveGauss (int radius, int hmin, int hmax) // only convolve height values in [hmin...hmax]
56 {
57 // create u and v vectors and restrict them to the interval [mincore...maxcore]
58 float core_u [MAXCORE], core_v [MAXCORE];
59 int mincorex = 0, mincorey = 0, maxcorex = 0, maxcorey = 0;
60 if (radius == 1)
61 {
62 core_u [4] = 0.25; core_u [5] = 0.5; core_u [6] = 0.25;
63 core_v [4] = 0.25; core_v [5] = 0.5; core_v [6] = 0.25;
64 mincorex = 4; maxcorex = 6;
65 mincorey = 4; maxcorey = 6;
66 }
67 else if (radius == 2)
68 {
69 core_u [3] = 0.1F; core_u [4] = 0.2F; core_u [5] = 0.4F; core_u [6] = 0.2F; core_u [7] = 0.1F;
70 core_v [3] = 0.1F; core_v [4] = 0.2F; core_v [5] = 0.4F; core_v [6] = 0.2F; core_v [7] = 0.1F;
71 mincorex = 3; maxcorex = 7;
72 mincorey = 3; maxcorey = 7;
73 }
74 else if (radius == 3)
75 {
76 core_u [2] = 0.05F; core_u [3] = 0.1F; core_u [4] = 0.2F; core_u [5] = 0.3F; core_u [6] = 0.2F; core_u [7] = 0.1F; core_u [8] = 0.05F;
77 core_v [2] = 0.05F; core_v [3] = 0.1F; core_v [4] = 0.2F; core_v [5] = 0.3F; core_v [6] = 0.2F; core_v [7] = 0.1F; core_v [8] = 0.05F;
78 mincorex = 2; maxcorex = 8;
79 mincorey = 2; maxcorey = 8;
80 }
81
82 // do the convolutions
83 int i, x, y, mx, my;
84 float sum;
85 float summe [MAXX + 1];
86 for (x = 0; x <= MAXX; x ++)
87 summe [x] = 0;
88 for (x = 0; x <= MAXX; x ++)
89 {
90 for (y = 0; y <= MAXX; y ++) // H conv u
91 {
92 summe [y] = 0;
93 for (i = mincorex; i <= maxcorex; i ++)
94 {
95 mx = GETCOORD(x - MAXCORE / 2 + i);
96 my = y;
97 summe [y] += core_u [i] * h [mx] [my];
98 }
99 }
100 for (y = 0; y <= MAXX; y ++) // H conv v
101 {
102 if (h [x] [y] >= hmin && h [x] [y] <= hmax) // only convolve if current height in [hmin...hmax]
103 {
104 sum = 0;
105 for (i = mincorey; i <= maxcorey; i ++)
106 {
107 my = GETCOORD(y - MAXCORE / 2 + i);
108 sum += core_v [i] * summe [my];
109 }
110 hg [x] [y] = (int) sum;
111 }
112 else
113 {
114 hg [x] [y] = h [x] [y];
115 }
116 }
117 }
118
119 // copy hg back to h
120 memcpy (h, hg, (MAXX+1) * (MAXX+1) * sizeof (unsigned short));
121 }
122
123 // 'smooth' the glaciers using an erosion function
smoothGlacier()124 void Landscape::smoothGlacier ()
125 {
126 int i, i2;
127 for (i = 0; i <= MAXX - 1; i ++)
128 for (i2 = 0; i2 <= MAXX - 1; i2 ++)
129 {
130 if (f [i] [i2] == GLACIER)
131 {
132 int min = h[i][i2];
133 min = min < h[i+1][i2] ? min : h[i+1][i2];
134 min = min < h[i][i2+1] ? min : h[i][i2+1];
135 min = min < h[i+1][i2+1] ? min : h[i+1][i2+1];
136 h[i][i2] = min;
137 }
138 }
139 }
140
141 // Gaussian convolution for a single raster point (5x5)
gauss(int x,int y)142 void Landscape::gauss (int x, int y)
143 {
144 if (x < 5) x = 5;
145 else if (x > MAXX - 5) x = MAXX - 5;
146 if (y < 5) y = 5;
147 else if (y > MAXX - 5) y = MAXX - 5;
148
149 int i, i2, i3, i4;
150 int hmask [5] [5];
151
152 int g5[5][5]={{1,1,2,1,1},
153 {1,3,4,3,1},
154 {2,4,5,4,2},
155 {1,3,4,3,1},
156 {1,1,2,1,1}};
157 for (i = x-2; i <= x+2; i ++)
158 for (i2 = y-2; i2 <= y+2; i2 ++)
159 {
160 int sum = 0;
161 for (i3 = 0; i3 < 5; i3 ++)
162 for (i4 = 0; i4 < 5; i4 ++)
163 {
164 sum += g5[i3][i4] * h[i+i3-2][i2+i4-2];
165 }
166 sum /= 53;
167 hmask [i-x+2] [i2-y+2] = sum;
168 }
169 for (i = x-2; i <= x+2; i ++)
170 for (i2 = y-2; i2 <= y+2; i2 ++)
171 {
172 h[i][i2] = hmask[2][2];
173 hw[i][i2] = hmask[2][2];
174 }
175 }
176
177 // constant height for a single raster point (7x7)
flatten(int x,int y,int dx,int dy)178 void Landscape::flatten (int x, int y, int dx, int dy)
179 {
180 int i, i2;
181 if (x < dx) x = dx;
182 else if (x > MAXX - dx) x = MAXX - dx;
183 if (y < dy) y = dy;
184 else if (y > MAXX - dy) y = MAXX - dy;
185
186 for (i = x-dx; i <= x+dx; i ++)
187 for (i2 = y-dy; i2 <= y+dy; i2 ++)
188 {
189 h[i][i2] = h[x][y];
190 hw[i][i2] = h[i][i2];
191 }
192 }
193
194
195
196 /****************************************************************************
197 LANDSCAPE TYPE QUERIES
198 ****************************************************************************/
199
isType(unsigned char type,unsigned char id)200 bool Landscape::isType (unsigned char type, unsigned char id)
201 {
202 return ((type & 0xFF) == (id << 0));
203 }
204
isWoods(int type)205 bool Landscape::isWoods (int type)
206 {
207 type &= 0xFF;
208 if (type >= CONIFEROUSWOODS0 && type <= BUSHES3)
209 return true;
210 return false;
211 }
212
isWater(int type)213 bool Landscape::isWater (int type)
214 {
215 type &= 0xFF;
216 if (type >= WATER && type <= XDEEPWATER)
217 return true;
218 return false;
219 }
220
isGlacier(int type)221 bool Landscape::isGlacier (int type)
222 {
223 type &= 0xFF;
224 if (type == GLACIER)
225 return true;
226 return false;
227 }
228
isGround(int x,int y)229 bool Landscape::isGround (int x, int y)
230 {
231 if (x < 0 || x > maxx || y < 0 || y > maxx) return false;
232 int type = f [y] [x];
233 if (!isWater (type))
234 return true;
235 return false;
236 }
237
238
239
240 /****************************************************************************
241 LANDSCAPE CREATION
242 ****************************************************************************/
243
init()244 void Landscape::init ()
245 {
246 int i, i2;
247 for (i = 0; i <= maxx; i ++)
248 for (i2 = 0; i2 <= maxx; i2 ++)
249 {
250 h [i] [i2] = 0; f [i] [i2] = 0;
251 }
252 }
253
254 // cubic spline interpolation (obsolete -> Gaussian convolution)
255 /* void interpolate (int n)
256 {
257 double s, r, q, a, b, c, d, e, f;
258 int i, i2, i3, i4;
259 long htest, p1, p2, p3, p4;
260 i3 = n;
261 i = 0;
262 while (i <= maxx)
263 {
264 i2 = 0;
265 while (i2 < maxx - (1 << i3))
266 {
267 a = i2 + 1;
268 b = i2 + (1 << i3) + 1;
269 c = i2 + (1 << (i3 + 1)) + 1;
270 d = h [(int) a - 1] [i];
271 e = h [(int) b - 1] [i];
272 f = h [(int) c - 1] [i];
273 double aq = a * a, bq = b * b, cq = c * c, mba = 1/b - 1/a, mca = 1/c - 1/a;
274 s = ((f/cq-d/aq)/mca-(e/bq-d/aq)/mba)/((1/cq-1/aq)/mca-(1/bq-1/aq)/mba);
275 r = ((e/bq-d/aq)/mba)-(1/bq-1/aq)/mba*s;
276 q = d/aq - r/a - s/aq;
277 for (i4 = (int) a + 1; i4 <= (int) c - 1; i4 ++)
278 {
279 if (i4 != b)
280 {
281 htest = (long) (i4 * i4 * q + i4 * r + s);
282 if (htest < 0) htest = 0;
283 if (htest > 65535) htest = 65535;
284 if (h [i4 - 1] [i] == 0)
285 {
286 h [i4 - 1] [i] = h [i4 - 1] [i] + (int) (htest / 2);
287 if (i4 - 1 < (1 << i3) || i4 - 1 > maxx - (1 << i3))
288 h [i4 - 1] [i] = h [i4 - 1] [i] * 2;
289 }
290 else
291 {
292 htest = htest / 2 + (htest - h [i4 - 1] [i] * 2) * (long) ((i4 - a) / (b - a) - 0.5);
293 if (htest < 0) htest = 0;
294 if (htest > 65535) htest = 65535;
295 h [i4 - 1] [i] = h [i4 - 1] [i] + (int) htest;
296 }
297 }
298 }
299 i2 = i2 + (1 << i3);
300 }
301 i = i + (1 << i3);
302 }
303 i2 = 0;
304 while (i2 <= maxx)
305 {
306 i = 0;
307 while (i < maxx - (1 << i3))
308 {
309 a = i + 1;
310 b = i + (1 << i3) + 1;
311 c = i + (1 << (i3 + 1)) + 1;
312 d = h [i2] [(int) a - 1];
313 e = h [i2] [(int) b - 1];
314 f = h [i2] [(int) c - 1];
315 double aq = a * a, bq = b * b, cq = c * c, mba = 1/b - 1/a, mca = 1/c - 1/a;
316 s = ((f/cq-d/aq)/mca-(e/bq-d/aq)/mba)/((1/cq-1/aq)/mca-(1/bq-1/aq)/mba);
317 r = ((e/bq-d/aq)/mba)-(1/bq-1/aq)/mba*s;
318 q = d/aq - r/a - s/aq;
319 for (i4 = (int) a + 1; i4 <= (int) c - 1; i4 ++)
320 {
321 if (i4 != b)
322 {
323 htest = (long) (i4 * i4 * q + i4 * r + s);
324 if (htest < 0) htest = 0;
325 if (htest > 65535) htest = 65535;
326 if (h [i2] [i4 - 1] == 0)
327 {
328 h [i2] [i4 - 1] = h [i2] [i4 - 1] + (int) (htest / 2);
329 if (i4 - 1 < (1 << i3) || i4 - 1 > maxx - (1 << i3))
330 h [i2] [i4 - 1] = h [i2] [i4 - 1] * 2;
331 }
332 else
333 {
334 htest = htest / 2 + (htest - h [i2] [i4 - 1] * 2) * (long) ((i4 - a) / (b - a) - 0.5);
335 if (htest < 0) htest = 0;
336 if (htest > 65535) htest = 65535;
337 h [i2] [i4 - 1] = h [i2] [i4 - 1] + (int) htest;
338 }
339 }
340 }
341 i = i + (1 << i3);
342 }
343 i2 ++;
344 }
345 }*/
346
genSurface(int hoehepc,int * heightmap)347 void Landscape::genSurface (int hoehepc, int *heightmap)
348 {
349 int i, i2, x, y;
350 int htest, h1, h2, step;
351 type = LAND_ALPINE;
352 hoehe = hoehepc * 512;
353 init ();
354 step = maxx / 4;
355 if (heightmap == NULL)
356 {
357 for (i = 0; i < 4; i ++)
358 for (i2 = 0; i2 < 4; i2 ++)
359 if (h [i * step] [i2 * step] == 0)
360 h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512);
361 for (i = 0; i < 5; i ++)
362 {
363 h [maxx] [i * step] = h [0] [i * step];
364 h [i * step] [maxx] = h [i * step] [0];
365 }
366 }
367 else
368 {
369 step /= 2; n --;
370 for (i = 0; i < 8; i ++)
371 for (i2 = 0; i2 < 8; i2 ++)
372 h [i * step] [i2 * step] = heightmap [i * 8 + i2];
373 for (i = 0; i < 9; i ++)
374 {
375 h [maxx] [i * step] = h [0] [i * step];
376 h [i * step] [maxx] = h [i * step] [0];
377 }
378 }
379 for (i = 2; i < n; i ++)
380 {
381 step = step / 2; y = 0;
382 do
383 {
384 x = step;
385 do
386 {
387 h1 = h [x - step] [y]; h2 = h [x + step] [y];
388 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
389 if (htest < 0) htest = 0;
390 if (htest > 65535) htest = 65535;
391 if (h [x] [y] == 0) h [x] [y] = htest;
392 x = x + 2 * step;
393 }
394 while (x != maxx + step);
395 y = y + 2 * step;
396 }
397 while (y < maxx);
398 for (x = step; x <= maxx - step; x += 2 * step)
399 h [x] [maxx] = h [x] [0];
400 x = 0;
401 do
402 {
403 y = step;
404 do
405 {
406 h1 = h [x] [y - step]; h2 = h [x] [y + step];
407 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
408 if (htest < 0) htest = 0;
409 if (htest > 65535) htest = 65535;
410 if (h [x] [y] == 0) h [x] [y] = htest;
411 y = y + 2 * step;
412 }
413 while (y <= maxx);
414 x = x + step;
415 }
416 while (x < maxx);
417 for (y = step; y <= maxx - step; y += 2 * step)
418 h [maxx] [y] = h [0] [y];
419 hoehe = (int) (hoehe / 1.1);
420 }
421 convolveGauss (2, 0, 35000);
422 convolveGauss (1, 35001, 65535);
423 highestpoint = 0;
424 lowestpoint = 65535;
425 for (i = 0; i < maxx; i ++)
426 for (i2 = 0; i2 < maxx; i2 ++)
427 {
428 if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2];
429 if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2];
430 }
431 }
432
genErosionSurface(int hoehepc,int * heightmap)433 void Landscape::genErosionSurface (int hoehepc, int *heightmap)
434 {
435 int i, i2, x, y;
436 int htest, h1, h2, step;
437 type = LAND_ALPINE;
438 hoehe = hoehepc * 512;
439 init ();
440 step = maxx / 4;
441 if (heightmap == NULL)
442 {
443 for (i = 0; i < 4; i ++)
444 for (i2 = 0; i2 < 4; i2 ++)
445 if (h [i * step] [i2 * step] == 0)
446 h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512);
447 for (i = 0; i < 5; i ++)
448 {
449 h [maxx] [i * step] = h [0] [i * step];
450 h [i * step] [maxx] = h [i * step] [0];
451 }
452 }
453 else
454 {
455 step /= 2; n --;
456 for (i = 0; i < 8; i ++)
457 for (i2 = 0; i2 < 8; i2 ++)
458 h [i * step] [i2 * step] = heightmap [i * 8 + i2];
459 for (i = 0; i < 9; i ++)
460 {
461 h [maxx] [i * step] = h [0] [i * step];
462 h [i * step] [maxx] = h [i * step] [0];
463 }
464 }
465 for (i = 2; i < n; i ++)
466 {
467 step = step / 2; y = 0;
468 do
469 {
470 x = step;
471 do
472 {
473 h1 = h [x - step] [y]; h2 = h [x + step] [y];
474 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
475 if (htest < 0) htest = 0;
476 if (htest > 65535) htest = 65535;
477 if (h [x] [y] == 0) h [x] [y] = htest;
478 x = x + 2 * step;
479 }
480 while (x != maxx + step);
481 y = y + 2 * step;
482 }
483 while (y < maxx);
484 for (x = step; x <= maxx - step; x += 2 * step)
485 h [x] [maxx] = h [x] [0];
486 x = 0;
487 do
488 {
489 y = step;
490 do
491 {
492 h1 = h [x] [y - step]; h2 = h [x] [y + step];
493 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
494 if (htest < 0) htest = 0;
495 if (htest > 65535) htest = 65535;
496 if (h [x] [y] == 0) h [x] [y] = htest;
497 y = y + 2 * step;
498 }
499 while (y <= maxx);
500 x = x + step;
501 }
502 while (x < maxx);
503 for (y = step; y <= maxx - step; y += 2 * step)
504 h [maxx] [y] = h [0] [y];
505 hoehe = (int) (hoehe / 1.1);
506 }
507 highestpoint = 0;
508 lowestpoint = 65535;
509 for (i = 0; i < maxx; i ++)
510 for (i2 = 0; i2 < maxx; i2 ++)
511 {
512 if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2];
513 if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2];
514 }
515 int erosion = (highestpoint - lowestpoint) / 5 + lowestpoint;
516 for (i = 0; i < maxx; i ++)
517 for (i2 = 0; i2 < maxx; i2 ++)
518 if (h [i] [i2] < erosion)
519 h [i] [i2] = erosion - 30 + myrandom (60, i, i2);
520 convolveGauss (2, 0, 35000);
521 convolveGauss (1, 35001, 65535);
522 }
523
genArcticSurface(int hoehepc,int * heightmap)524 void Landscape::genArcticSurface (int hoehepc, int *heightmap)
525 {
526 int i, i2, x, y;
527 int htest, h1, h2, step;
528 type = LAND_ARCTIC;
529 hoehe = hoehepc * 512;
530 init ();
531 step = maxx / 4;
532 if (heightmap == NULL)
533 {
534 for (i = 0; i < 4; i ++)
535 for (i2 = 0; i2 < 4; i2 ++)
536 if (h [i * step] [i2 * step] == 0)
537 h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512);
538 for (i = 0; i < 5; i ++)
539 {
540 h [maxx] [i * step] = h [0] [i * step];
541 h [i * step] [maxx] = h [i * step] [0];
542 }
543 }
544 else
545 {
546 step /= 2; n --;
547 for (i = 0; i < 8; i ++)
548 for (i2 = 0; i2 < 8; i2 ++)
549 h [i * step] [i2 * step] = heightmap [i * 8 + i2];
550 for (i = 0; i < 9; i ++)
551 {
552 h [maxx] [i * step] = h [0] [i * step];
553 h [i * step] [maxx] = h [i * step] [0];
554 }
555 }
556 for (i = 2; i < n; i ++)
557 {
558 step = step / 2; y = 0;
559 do
560 {
561 x = step;
562 do
563 {
564 h1 = h [x - step] [y]; h2 = h [x + step] [y];
565 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
566 if (htest < 0) htest = 0;
567 if (htest > 65535) htest = 65535;
568 if (h [x] [y] == 0) h [x] [y] = htest;
569 x = x + 2 * step;
570 }
571 while (x != maxx + step);
572 y = y + 2 * step;
573 }
574 while (y < maxx);
575 for (x = step; x <= maxx - step; x += 2 * step)
576 h [x] [maxx] = h [x] [0];
577 x = 0;
578 do
579 {
580 y = step;
581 do
582 {
583 h1 = h [x] [y - step]; h2 = h [x] [y + step];
584 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
585 if (htest < 0) htest = 0;
586 if (htest > 65535) htest = 65535;
587 if (h [x] [y] == 0) h [x] [y] = htest;
588 y = y + 2 * step;
589 }
590 while (y <= maxx);
591 x = x + step;
592 }
593 while (x < maxx);
594 for (y = step; y <= maxx - step; y += 2 * step)
595 h [maxx] [y] = h [0] [y];
596 hoehe = (int) (hoehe / 1.1);
597 }
598 convolveGauss (2, 0, 35000);
599 highestpoint = 0;
600 lowestpoint = 65535;
601 for (i = 0; i < maxx; i ++)
602 for (i2 = 0; i2 < maxx; i2 ++)
603 {
604 if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2];
605 if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2];
606 f [i] [i2] = GLACIER;
607 if (abs (h [i] [i2] - h [i + 1] [i2]) > 300) f [i] [i2] = ROCKS;
608 if (abs (h [i] [i2] - h [i] [i2 + 1]) > 300) f [i] [i2] = ROCKS;
609 if (h [i] [i2] < 32836 - hoehepc * 3)
610 {
611 int dh = 32836 - hoehepc * 3 - h [i] [i2];
612 if (dh < 2000)
613 f [i] [i2] = SHALLOWWATER;
614 else
615 f [i] [i2] = DEEPWATER;
616 hw [i] [i2] = 32836 - hoehepc * 3;
617 }
618 }
619 }
620
genMoonSurface(int height)621 void Landscape::genMoonSurface (int height)
622 {
623 int i, i2, i3, x, y;
624 int radius, rad, depth, depth2;
625 double pi = 3.14;
626
627 type = LAND_MOON;
628 for (i = 0; i <= MAXX; i ++)
629 for (i2 = 0; i2 <= MAXX; i2 ++)
630 h [i] [i2] = 30000 + myrandom (300, i, i2);
631
632 int maxholes = 1;
633 for (i = 0; i < maxholes; i ++)
634 {
635 x = myrandom (MAXX + 1);
636 y = myrandom (MAXX + 1);
637 radius = myrandom (50) + 200;
638 depth = radius * height / 2;
639 for (i2 = x - radius; i2 < x+radius; i2++)
640 for (i3 = y - radius; i3 < y+radius; i3++)
641 {
642 rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3));
643 if (rad < radius)
644 {
645 if (rad < 0.67 * radius)
646 {
647 depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth);
648 }
649 else
650 {
651 depth2 = (int) (0.3 * sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1));
652 }
653 h[getCoord(i2)][getCoord(i3)] -= depth2;
654 }
655 }
656 }
657
658 maxholes = myrandom (4) + 8 ;
659 for (i = 0; i < maxholes; i++)
660 {
661 x = myrandom (MAXX + 1);
662 y = myrandom (MAXX + 1);
663 radius = myrandom (50) + 50;
664 depth = radius * height / 2;
665 for (i2 = x - radius; i2 < x+radius; i2++)
666 for (i3 = y - radius; i3 < y+radius; i3++)
667 {
668 rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3));
669 if (rad < radius)
670 {
671 if (rad < 0.67 * radius)
672 {
673 depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth);
674 }
675 else
676 {
677 depth2 = (int) (0.3 * sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1));
678 }
679 h[getCoord(i2)][getCoord(i3)] -= depth2;
680 }
681 }
682
683 }
684
685 maxholes = myrandom (10) + 20 ;
686 for (i = 0; i < maxholes; i++)
687 {
688 x = myrandom (MAXX + 1);
689 y = myrandom (MAXX + 1);
690 radius = myrandom (20) + 20;
691 depth = radius * height / 2;
692 for (i2 = x - radius; i2 < x+radius; i2++)
693 for (i3 = y - radius; i3 < y+radius; i3++)
694 {
695 rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3));
696 if (rad < radius)
697 {
698 if (rad < 0.67 * radius)
699 {
700 depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth);
701 }
702 else
703 {
704 depth2 = (int) (0.6 * sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1));
705 }
706 h[getCoord(i2)][getCoord(i3)] -= depth2;
707 }
708 }
709 }
710
711 maxholes = myrandom (50) + 400;
712 for (i = 0; i < maxholes; i++)
713 {
714 x = myrandom (MAXX + 1);
715 y = myrandom (MAXX + 1);
716 radius = myrandom (10) + 5;
717 depth = radius * height / 3;
718 for (i2 = x - radius; i2 < x+radius; i2++)
719 for (i3 = y - radius; i3 < y+radius; i3++)
720 {
721 rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3));
722 if (rad < radius)
723 {
724 if (rad < 0.67 * radius) depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth);
725 else depth2 = (int) (sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1));
726 h[getCoord(i2)][getCoord(i3)] -= depth2;
727 }
728 }
729
730 }
731 convolveGauss (2, 0, 65535);
732 }
733
genCanyonSurface(int hoehepc)734 void Landscape::genCanyonSurface (int hoehepc)
735 {
736 int i, i2, x, y;
737 int htest, h1, h2, step;
738 type = LAND_CANYON;
739 hoehe = hoehepc * 512;
740 init ();
741 step = maxx / 16;
742 int minh = 0;
743 int maxh = 127 * 256 + 64 * hoehe / 1024;
744 for (i = 0; i < 16; i ++)
745 for (i2 = 0; i2 < 16; i2 ++)
746 if (h [i * step] [i2 * step] == 0)
747 if (myrandom (2, i, i2))
748 h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024;
749 else
750 h [i * step] [i2 * step] = 127 * 256 + 64 * hoehe / 1024;
751 for (i = 0; i < 17; i ++)
752 {
753 h [maxx] [i * step] = h [0] [i * step];
754 h [i * step] [maxx] = h [i * step] [0];
755 }
756 for (i = 4; i < n; i ++)
757 {
758 step = step / 2; y = 0;
759 do
760 {
761 x = step;
762 do
763 {
764 h1 = h [x - step] [y]; h2 = h [x + step] [y];
765 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
766 if (htest < minh) htest = minh;
767 if (htest > maxh) htest = maxh;
768 if (h [x] [y] == 0) h [x] [y] = htest;
769 x = x + 2 * step;
770 }
771 while (x != maxx + step);
772 y = y + 2 * step;
773 }
774 while (y < maxx);
775 for (x = step; x <= maxx - step; x += 2 * step)
776 h [x] [maxx] = h [x] [0];
777 x = 0;
778 do
779 {
780 y = step;
781 do
782 {
783 h1 = h [x] [y - step]; h2 = h [x] [y + step];
784 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
785 if (htest < minh) htest = minh;
786 if (htest > maxh) htest = maxh;
787 if (h [x] [y] == 0) h [x] [y] = htest;
788 y = y + 2 * step;
789 }
790 while (y <= maxx);
791 x = x + step;
792 }
793 while (x < maxx);
794 for (y = step; y <= maxx - step; y += 2 * step)
795 h [maxx] [y] = h [0] [y];
796 hoehe = (int) (hoehe / 1.1);
797 }
798 for (i = 0; i <= MAXX; i ++)
799 for (i2 = 0; i2 <= MAXX; i2 ++)
800 if (h [i] [i2] > 32836 - hoehepc * 30)
801 h [i] [i2] -= h [i] [i2] % 2600;
802 for (i = 0; i <= MAXX; i ++)
803 for (i2 = 0; i2 <= MAXX; i2 ++)
804 f [i] [i2] = REDSTONE;
805 convolveGauss (3, 0, 35000);
806 convolveGauss (2, 35001, 65535);
807 for (i = 0; i < MAXX; i ++)
808 for (i2 = 0; i2 < MAXX; i2 ++)
809 {
810 if (abs (h [i] [i2] - h [i + 1] [i2]) < 200 && abs (h [i] [i2] - h [i] [i2 + 1]) < 200)
811 {
812 f [i] [i2] = REDSAND;
813 if (h [i] [i2] > 30000 && !myrandom (80) && hoehepc > 20)
814 f [i] [i2] = REDTREE0;
815 }
816 if (hoehepc > 20)
817 {
818 if (h [i] [i2] < 32836 - hoehepc * 40)
819 {
820 int dh = 32836 - hoehepc * 40 - h [i] [i2];
821 if (dh < 1500)
822 f [i] [i2] = SHALLOWWATER;
823 else
824 f [i] [i2] = DEEPWATER;
825 hw [i] [i2] = 32836 - hoehepc * 40;
826 }
827 }
828 }
829
830 highestpoint = 0;
831 lowestpoint = 65535;
832 for (i = 0; i < maxx; i ++)
833 for (i2 = 0; i2 < maxx; i2 ++)
834 {
835 if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2];
836 if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2];
837 }
838 }
839
genDesertSurface(int hoehepc)840 void Landscape::genDesertSurface (int hoehepc)
841 {
842 int i, i2, x, y;
843 int htest, h1, h2, step;
844 type = LAND_DESERT;
845 hoehe = hoehepc * 512;
846 init ();
847 step = maxx / 16;
848 for (i = 0; i < 16; i ++)
849 for (i2 = 0; i2 < 16; i2 ++)
850 if (h [i * step] [i2 * step] == 0)
851 h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512);
852 for (i = 0; i < 17; i ++)
853 {
854 h [maxx] [i * step] = h [0] [i * step];
855 h [i * step] [maxx] = h [i * step] [0];
856 }
857 for (i = 4; i < n; i ++)
858 {
859 step = step / 2; y = 0;
860 do
861 {
862 x = step;
863 do
864 {
865 h1 = h [x - step] [y]; h2 = h [x + step] [y];
866 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
867 if (htest < 0) htest = 0;
868 if (htest > 65535) htest = 65535;
869 if (h [x] [y] == 0) h [x] [y] = htest;
870 x = x + 2 * step;
871 }
872 while (x != maxx + step);
873 y = y + 2 * step;
874 }
875 while (y < maxx);
876 for (x = step; x <= maxx - step; x += 2 * step)
877 h [x] [maxx] = h [x] [0];
878 x = 0;
879 do
880 {
881 y = step;
882 do
883 {
884 h1 = h [x] [y - step]; h2 = h [x] [y + step];
885 htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y);
886 if (htest < 0) htest = 0;
887 if (htest > 65535) htest = 65535;
888 if (h [x] [y] == 0) h [x] [y] = htest;
889 y = y + 2 * step;
890 }
891 while (y <= maxx);
892 x = x + step;
893 }
894 while (x < maxx);
895 for (y = step; y <= maxx - step; y += 2 * step)
896 h [maxx] [y] = h [0] [y];
897 hoehe = (int) (hoehe / 1.5);
898 }
899 convolveGauss (2, 0, 65535);
900 int i3;
901 for (i = 0; i <= MAXX; i ++)
902 for (i2 = 0; i2 <= MAXX; i2 ++)
903 {
904 const int range = 11;
905 int ha [range];
906 for (i3 = 0; i3 < range; i3 ++)
907 ha [i3] = h [i] [GETCOORD(i2 + i3 - range / 2)];
908 int hmin = 65000, hmax = 0;
909 for (i3 = 0; i3 < range; i3 ++)
910 {
911 if (ha [i3] < hmin) hmin = ha [i3];
912 if (ha [i3] > hmax) hmax = ha [i3];
913 }
914 if (ha [range / 2 + 1] < ha [range / 2 - 1])
915 {
916 hg [i] [i2] = hmin;
917 }
918 else
919 {
920 hg [i] [i2] = hmax;
921 }
922 }
923 convolveGauss (2, 0, 65535);
924 for (i = 0; i <= MAXX; i ++)
925 for (i2 = 0; i2 <= MAXX; i2 ++)
926 h [i] [i2] = hg [i] [i2];
927 for (i = 0; i <= MAXX; i ++)
928 for (i2 = 0; i2 <= MAXX; i2 ++)
929 f [i] [i2] = DESERTSAND;
930 for (i = 0; i < MAXX; i += 4)
931 for (i2 = 0; i2 < MAXX; i2 += 4)
932 {
933 if (!myrandom (50))
934 f [i] [i2] = CACTUS0;
935 }
936 highestpoint = 0;
937 lowestpoint = 65535;
938 for (i = 0; i < maxx; i ++)
939 for (i2 = 0; i2 < maxx; i2 ++)
940 {
941 if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2];
942 if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2];
943 }
944 }
945
genTrench(int width,int height)946 void Landscape::genTrench (int width, int height)
947 {
948 int i, i2;
949 int midleft = MAXX / 2 - width / 2, midright = MAXX / 2 + width / 2;
950 int left = 0, right = 0;
951 for (i = 0; i <= MAXX; i ++)
952 {
953 if (i != 148 && i != 52)
954 {
955 for (i2 = midleft + left; i2 < midright + right; i2 ++)
956 {
957 int height1 = height;
958 if (i2 - midleft - left < 4)
959 {
960 height1 = height1 * (i2 - midleft - left) / 4;
961 f [i] [i2] = REDSTONE;
962 }
963 if (i2 > midright + right - 4)
964 {
965 height1 = height1 * (midright + right - i2) / 4;
966 f [i] [i2] = REDSTONE;
967 }
968 h [i] [i2] -= height1;
969 }
970 if (i & 1)
971 {
972 left += myrandom (5) - 2;
973 right += myrandom (5) - 2;
974 if (left < -5) left = -5;
975 if (left > 5) left = 5;
976 if (right < -5) right = -5;
977 if (right > 5) right = 5;
978 }
979 }
980 else
981 {
982 h [i] [MAXX / 2] -= height;
983 }
984 }
985 lowestpoint -= height;
986 }
987
988
989
990 /****************************************************************************
991 CREATE ROCKS
992 ****************************************************************************/
993
genRocks(int diffmin,int percent)994 void Landscape::genRocks (int diffmin, int percent)
995 {
996 int i, i2, i3, i4, i5, d = 150;
997 long hmin, hmax;
998 long htest;
999 double r, rd;
1000 rockborder = 65535;
1001 hmax = highestpoint; hmin = lowestpoint;
1002 if (hmax - hmin >= (long) diffmin * 256) // Generation
1003 for (i = 0; i < maxx; i ++)
1004 for (i2 = 0; i2 < maxx; i2 ++)
1005 {
1006 r = (hmax - hmin) / 100 * percent;
1007 rd = h [i] [i2];
1008 rd = rd - h [i + 1] [i2] / 3 - h [i] [i2 + 1] / 3 - h [i + 1] [i2 + 1] / 3;
1009 rd = fabs (rd);
1010 int minrock = 0;
1011 if (percent > 50) minrock = (percent - 50) * 8;
1012 if (h [i] [i2] > hmax - r)
1013 {
1014 if (rd + minrock >= 800 - 800 * (h [i] [i2] - r) / (hmax - r))
1015 {
1016 f [i] [i2] = ROCKS + myrandom (2);
1017 htest = h [i] [i2] - d + myrandom (d * 2);
1018 if (htest > 65535) htest = 65535;
1019 h [i] [i2] = (unsigned short) htest;
1020 if (h [i] [i2] < rockborder) rockborder = h [i] [i2];
1021 }
1022 else if (rd + minrock >= 500 - 500 * (h [i] [i2] - r) / (hmax - r))
1023 {
1024 f [i] [i2] = GRAVEL;
1025 }
1026 }
1027 if (abs (h [i] [i2] - h [i + 1] [i2]) >= 600 || abs (h [i] [i2] - h [i] [i2 + 1]) >= 600)
1028 {
1029 f [i] [i2] = ROCKS + myrandom (2);
1030 htest = h [i] [i2] - d + myrandom (d * 2);
1031 if (htest > 65535) htest = 65535;
1032 h [i] [i2] = (unsigned short) htest;
1033 }
1034 if (h [i] [i2] > hmax - r / 2)
1035 if (rd < 200 * (h [i] [i2] - r / 2) / (hmax - r / 2))
1036 f [i] [i2] = GLACIER;
1037 }
1038 for (i = 1; i < maxx; i ++) // L�cken schlie�en
1039 for (i2 = 1; i2 < maxx; i2 ++)
1040 {
1041 if (f [i] [i2] != ROCKS)
1042 if (f [i - 1] [i2] == ROCKS && f [i + 1] [i2] == ROCKS ||
1043 f [i] [i2 - 1] == ROCKS && f [i] [i2 + 1] == ROCKS)
1044 f [i] [i2] = ROCKS;
1045 if (f [i] [i2] != ROCKS)
1046 if (f [i - 1] [i2] == GLACIER && f [i + 1] [i2] == GLACIER ||
1047 f [i] [i2 - 1] == GLACIER && f [i] [i2 + 1] == GLACIER)
1048 f [i] [i2] = GLACIER;
1049 }
1050 for (i = 1; i < maxx; i ++) // Felsengebiet uneben
1051 for (i2 = 1; i2 < maxx; i2 ++)
1052 if (f [i] [i2] == ROCKS)
1053 {
1054 i5 = 0;
1055 for (i3 = -1; i3 <= 1; i3 ++)
1056 for (i4 = -1; i4 <= 1; i4 ++)
1057 if (f [i + i3] [i2 + i4] == ROCKS)
1058 i5 ++;
1059 htest = (long) h [i] [i2] + (long) i5 * 50;
1060 if (htest > 65535) htest = 65535;
1061 h [i] [i2] = (unsigned short) htest;
1062 }
1063 smoothGlacier ();
1064 }
1065
1066
1067
1068 /****************************************************************************
1069 CREATE LAKES
1070 ****************************************************************************/
1071
calcLake(int ys,int xs,unsigned short level,int num,int maxextent)1072 int Landscape::calcLake (int ys, int xs, unsigned short level, int num, int maxextent)
1073 {
1074 int i, i2, n, w, timeout = 0;
1075 bool hits;
1076 unsigned char sn = (unsigned char) num;
1077 int extent = 0;
1078 // h [xs] [ys] = level;
1079 w = 5;
1080 if (xs <= 0) xs = 1;
1081 if (ys <= 0) ys = 1;
1082 if (xs >= maxx) xs = maxx - 1;
1083 if (ys >= maxx) ys = maxx - 1;
1084 ftry [xs] [ys] = sn;
1085 do
1086 {
1087 timeout ++;
1088 i2 = 0; hits = false;
1089 while (i2 < maxx * 2)
1090 {
1091 i2 ++;
1092 n = i2;
1093 if (n > maxx) n = n - maxx * 2 + 1;
1094 for (i = xs; i < maxx; i ++)
1095 {
1096 if (ys - n >= 0 && ys - n < maxx)
1097 if (h [i] [ys - n] < level && ftry [i] [ys - n] != sn)
1098 if ((ftry [i - 1] [ys - n] == sn) || (ftry [i] [ys - n + 1] == sn) ||
1099 (ftry [i + 1] [ys - n + 1] == sn) || (ftry [i - 1] [ys - n + 1] == sn))
1100 {
1101 ftry [i] [ys - n] = sn; extent ++; hits = true;
1102 }
1103 if (ys + n > 0 && ys + n <= maxx)
1104 if (h [i] [ys + n] < level && ftry [i] [ys + n] != sn)
1105 if ((ftry [i - 1] [ys + n] == sn) || (ftry [i] [ys + n - 1] == sn) ||
1106 (ftry [i + 1] [ys + n - 1] == sn) || (ftry [i - 1] [ys + n - 1] == sn))
1107 {
1108 ftry [i] [ys + n] = sn; extent ++; hits = true;
1109 }
1110 }
1111 for (i = xs; i > 0; i --)
1112 {
1113 if (ys - n >= 0 && ys - n < maxx)
1114 if (h [i] [ys - n] < level && ftry [i] [ys - n] != sn)
1115 if ((ftry [i + 1] [ys - n] == sn) || (ftry [i] [ys - n + 1] == sn) ||
1116 (ftry [i + 1] [ys - n + 1] == sn) || (ftry [i - 1] [ys - n + 1] == sn))
1117 {
1118 ftry [i] [ys - n] = sn; extent ++; hits = true;
1119 }
1120 if (ys + n > 0 && ys + n <= maxx)
1121 if (h [i] [ys + n] < level && ftry [i] [ys + n] != sn)
1122 if ((ftry [i + 1] [ys + n] == sn) || (ftry [i] [ys + n - 1] == sn) ||
1123 (ftry [i + 1] [ys + n - 1] == sn) || (ftry [i - 1] [ys + n - 1] == sn))
1124 {
1125 ftry [i] [ys + n] = sn; extent ++; hits = true;
1126 }
1127 }
1128 for (i = ys; i < maxx; i ++)
1129 {
1130 if (xs - n >= 0 && xs - n < maxx)
1131 if (h [xs - n] [i] < level && ftry [xs - n] [i] != sn)
1132 if ((ftry [xs - n] [i - 1] == sn) || (ftry [xs - n + 1] [i] == sn) ||
1133 (ftry [xs - n + 1] [i + 1] == sn) || (ftry [xs - n + 1] [i - 1] == sn))
1134 {
1135 ftry [xs - n] [i] = sn; extent ++; hits = true;
1136 }
1137 if (xs + n > 0 && xs + n <= maxx)
1138 if (h [xs + n] [i] < level && ftry [xs + n] [i] != sn)
1139 if ((ftry [xs + n] [i - 1] == sn) || (ftry [xs + n - 1] [i] == sn) ||
1140 (ftry [xs + n - 1] [i + 1] == sn) || (ftry [xs + n - 1] [i - 1] == sn))
1141 {
1142 ftry [xs + n] [i] = sn; extent ++; hits = true;
1143 }
1144 }
1145 for (i = ys; i > 0; i --)
1146 {
1147 if (xs - n >= 0 && xs - n < maxx)
1148 if (h [xs - n] [i] < level && ftry [xs - n] [i] != sn)
1149 if ((ftry [xs - n] [i + 1] == sn) || (ftry [xs - n + 1] [i] == sn) ||
1150 (ftry [xs - n + 1] [i + 1] == sn) || (ftry [xs - n + 1] [i - 1] == sn))
1151 {
1152 ftry [xs - n] [i] = sn; extent ++; hits = true;
1153 }
1154 if (xs + n > 0 && xs + n <= maxx)
1155 if (h [xs + n] [i] < level && ftry [xs + n] [i] != sn)
1156 if ((ftry [xs + n] [i - 1] == sn) || (ftry [xs + n - 1] [i] == sn) ||
1157 (ftry [xs + n - 1] [i + 1] == sn) || (ftry [xs + n - 1] [i - 1] == sn))
1158 {
1159 ftry [xs + n] [i] = sn; extent ++; hits = true;
1160 }
1161 }
1162 }
1163 if (extent > maxextent)
1164 return -1;
1165 }
1166 while (hits && timeout < 10);
1167 if (timeout >= 10)
1168 return -1;
1169 return extent;
1170 }
1171
genLake(int depthpc)1172 void Landscape::genLake (int depthpc)
1173 {
1174 for (int j = 0; j < 5; j ++)
1175 {
1176 int a1, i, i2;
1177 unsigned short level, zmin;
1178 int xs = 0, ys = 0;
1179 unsigned short depth = (highestpoint - lowestpoint) * depthpc / 100;
1180 zmin = 65535;
1181 int radius = MAXX * 2 * depthpc / 100;
1182 a1 = maxx / 8;
1183 for (i = 0; i < 20; i ++)
1184 {
1185 xs = myrandom (MAXX - 2 * a1) + a1;
1186 ys = myrandom (MAXX - 2 * a1) + a1;
1187 if (hw [ys] [xs] == 0) break;
1188 }
1189 if (i == 20) return;
1190 int minx = xs - radius, miny = ys - radius;
1191 int maxx = xs + radius, maxy = ys + radius;
1192 if (minx < 1) minx = 1;
1193 if (maxx > MAXX - 1) maxx = MAXX - 1;
1194 if (miny < 1) miny = 1;
1195 if (maxy > MAXX - 1) maxy = MAXX - 1;
1196 xs = -1; ys = -1;
1197 for (i = miny; i < maxy; i += 2)
1198 for (i2 = minx; i2 < maxx; i2 += 2)
1199 if (h [i] [i2] < zmin && hw [i] [i2] == 0)
1200 {
1201 zmin = h [i] [i2];
1202 xs = i2; ys = i;
1203 }
1204 int extent = 0;
1205 if (xs >= 0)
1206 {
1207 level = zmin + depth;
1208 for (i = 0; i <= MAXX; i ++)
1209 for (i2 = 0; i2 <= MAXX; i2 ++)
1210 {
1211 ftry [i] [i2] = GRASS;
1212 }
1213 extent = calcLake (xs, ys, level, TRYLAKE, radius * radius / 2);
1214 if (extent <= 0) break;
1215 for (i = 0; i <= MAXX; i ++)
1216 {
1217 if (ftry [i] [0] != ftry [i] [MAXX])
1218 {
1219 if (ftry [i] [0] == TRYLAKE)
1220 extent += calcLake (MAXX, i, level, TRYLAKE, radius * radius / 2);
1221 else
1222 extent += calcLake (0, i, level, TRYLAKE, radius * radius / 2);
1223 if (extent <= 0) break;
1224 }
1225 }
1226 if (extent > 0)
1227 for (i = 0; i <= MAXX; i ++)
1228 {
1229 if (ftry [0] [i] != ftry [MAXX] [i])
1230 {
1231 if (ftry [0] [i] == TRYLAKE)
1232 extent += calcLake (i, MAXX, level, TRYLAKE, radius * radius / 2);
1233 else
1234 extent += calcLake (i, 0, level, TRYLAKE, radius * radius / 2);
1235 if (extent <= 0) break;
1236 }
1237 }
1238 int waterlevel1 = 300;
1239 int waterlevel2 = 600;
1240 int waterlevel3 = 1400;
1241 int waterlevel4 = 2000;
1242 if (type == LAND_CANYON)
1243 {
1244 waterlevel1 = 400;
1245 waterlevel2 = 800;
1246 waterlevel3 = 1500;
1247 waterlevel4 = 2000;
1248 }
1249 for (i = 0; i <= MAXX; i ++)
1250 for (i2 = 0; i2 <= MAXX; i2 ++)
1251 if (ftry [i] [i2] == TRYLAKE)
1252 {
1253 ftry [i] [i2] = GRASS;
1254 if (level - h [i] [i2] < waterlevel1)
1255 f [i] [i2] = XSHALLOWWATER;
1256 else if (level - h [i] [i2] < waterlevel2)
1257 f [i] [i2] = SHALLOWWATER;
1258 else if (level - h [i] [i2] < waterlevel3)
1259 f [i] [i2] = WATER;
1260 else if (level - h [i] [i2] < waterlevel4)
1261 f [i] [i2] = DEEPWATER;
1262 else
1263 f [i] [i2] = XDEEPWATER;
1264 hw [i] [i2] = level; // + myrandom (w);
1265 }
1266
1267 int barrage = ROCKS;
1268 for (i = 0; i <= MAXX; i ++)
1269 {
1270 if (hw [i] [0] != hw [i] [MAXX]) // error: water and landscape at different heights => make a barrage
1271 {
1272 if (hw [i] [0] == 0)
1273 {
1274 h [i] [MAXX - 2] = hw [i] [MAXX] + 100;
1275 h [i] [MAXX - 1] = hw [i] [MAXX] + 100;
1276 h [i] [MAXX] = h [i] [MAXX - 1];
1277 h [i] [0] = h [i] [MAXX];
1278 for (i2 = 1; i2 < 5; i2 ++)
1279 if (h [i] [i2] < h [i] [0] - i2 * 1000)
1280 {
1281 h [i] [i2] = h [i] [0] - i2 * 1000;
1282 f [i] [i2] = barrage;
1283 f [i] [i2 + 1] = barrage;
1284 }
1285 f [i] [MAXX - 2] = barrage;
1286 f [i] [MAXX - 1] = barrage;
1287 f [i] [MAXX] = barrage;
1288 f [i] [0] = barrage;
1289 f [i] [1] = barrage;
1290 }
1291 else if (hw [i] [MAXX] == 0)
1292 {
1293 h [i] [2] = hw [i] [0] + 100;
1294 h [i] [1] = hw [i] [0] + 100;
1295 h [i] [0] = h [i] [1];
1296 h [i] [MAXX] = h [i] [0];
1297 for (i2 = 1; i2 < 5; i2 ++)
1298 if (h [i] [MAXX - i2] < h [i] [MAXX] - i2 * 1000)
1299 {
1300 h [i] [MAXX - i2] = h [i] [MAXX] - i2 * 1000;
1301 f [i] [MAXX - i2] = barrage;
1302 f [i] [MAXX - i2 - 1] = barrage;
1303 }
1304 f [i] [2] = barrage;
1305 f [i] [1] = barrage;
1306 f [i] [0] = barrage;
1307 f [i] [MAXX] = barrage;
1308 f [i] [MAXX - 1] = barrage;
1309 }
1310 }
1311 if (hw [0] [i] != hw [MAXX] [i]) // error: water and landscape at different heights => make a barrage
1312 {
1313 if (hw [0] [i] == 0)
1314 {
1315 h [MAXX - 2] [i] = hw [MAXX] [i] + 100;
1316 h [MAXX - 1] [i] = hw [MAXX] [i] + 100;
1317 h [MAXX] [i] = h [MAXX - 1] [i];
1318 h [0] [i] = h [MAXX] [i];
1319 for (i2 = 1; i2 < 5; i2 ++)
1320 if (h [i2] [i] < h [0] [i] - i2 * 1000)
1321 {
1322 h [i2] [i] = h [0] [i] - i2 * 1000;
1323 f [i2] [i] = barrage;
1324 f [i2 + 1] [i] = barrage;
1325 }
1326 f [MAXX - 2] [i] = barrage;
1327 f [MAXX - 1] [i] = barrage;
1328 f [MAXX] [i] = barrage;
1329 f [0] [i] = barrage;
1330 f [1] [i] = barrage;
1331 }
1332 else if (hw [MAXX] [i] == 0)
1333 {
1334 h [2] [i] = hw [0] [i] + 100;
1335 h [1] [i] = hw [0] [i] + 100;
1336 h [0] [i] = h [1] [i];
1337 h [MAXX] [i] = h [0] [i];
1338 for (i2 = 1; i2 < 5; i2 ++)
1339 if (h [MAXX - i2] [i] < h [MAXX] [i] - i2 * 1000)
1340 {
1341 h [MAXX - i2] [i] = h [MAXX] [i] - i2 * 1000;
1342 f [MAXX - i2] [i] = barrage;
1343 f [MAXX - i2 - 1] [i] = barrage;
1344 }
1345 f [2] [i] = barrage;
1346 f [1] [i] = barrage;
1347 f [0] [i] = barrage;
1348 f [MAXX] [i] = barrage;
1349 f [MAXX - 1] [i] = barrage;
1350 }
1351 }
1352 }
1353 return;
1354 }
1355 }
1356 }
1357
1358
1359
1360 /****************************************************************************
1361 CREATE WOODS
1362 ****************************************************************************/
1363
calcWoods(int dy)1364 void Landscape::calcWoods (int dy)
1365 {
1366 int i, i2;
1367 int var = 2000;
1368 for (i = 0; i < maxx; i ++)
1369 for (i2 = 0; i2 < maxx; i2 ++)
1370 {
1371 if (fabs (h [i] [i2] - h [i + 1] [i2]) > dy)
1372 if (f [i] [i2] == 0)
1373 {
1374 int ra = myrandom (3);
1375 if (h [i] [i2] >= rockborder + 3000 + myrandom (var)) f [i] [i2] = (DWARFPINES1 + ra);
1376 else if (h [i] [i2] >= 15000 + myrandom (var) && h [i] [i2] < rockborder - 10000 + myrandom (var)) f [i] [i2] = (MIXEDWOODS1 + ra);
1377 else if (h [i] [i2] < 15000 + var) f [i] [i2] = (CONIFEROUSWOODS1 + ra);
1378 else f [i] [i2] = (DECIDUOUSWOODS1 + ra);
1379 }
1380 }
1381 for (i = 1; i < maxx; i ++)
1382 for (i2 = 1; i2 < maxx; i2 ++)
1383 if (f [i] [i2] == 0)
1384 if (isWoods (f [i - 1] [i2]) && isWoods (f [i + 1] [i2]) ||
1385 isWoods (f [i] [i2 - 1]) && isWoods (f [i] [i2 + 1]))
1386 {
1387 int ra = myrandom (3);
1388 if (h [i] [i2] >= rockborder + 3000 + myrandom (var)) f [i] [i2] = (DWARFPINES1 + ra);
1389 else if (h [i] [i2] >= 15000 + myrandom (var) && h [i] [i2] < rockborder - 10000 + myrandom (var)) f [i] [i2] = (BUSHES1 + ra);
1390 else if (h [i] [i2] < 15000 + var) f [i] [i2] = (BUSHES1 + ra);
1391 else f [i] [i2] = (BUSHES1 + ra);
1392 }
1393 for (i = 4; i < maxx - 4; i ++)
1394 for (i2 = 4; i2 < maxx - 4; i2 ++)
1395 if (isWoods (f [i - 4] [i2]) && isWoods (f [i + 4] [i2]) &&
1396 isWoods (f [i] [i2 - 4]) && isWoods (f [i] [i2 + 4]) &&
1397 isWoods (f [i] [i2]))
1398 {
1399 f [i] [i2] --;
1400 }
1401 for (i = 1; i < maxx; i ++)
1402 for (i2 = 1; i2 < maxx; i2 ++)
1403 if (f [i] [i2] == f [i + 1] [i2] && f [i] [i2] == f [i - 1] [i2] &&
1404 f [i] [i2] == f [i] [i2 + 1] && f [i] [i2] == f [i] [i2 - 1])
1405 {
1406 if ((f [i] [i2] & 4) == 1) f [i] [i2] ++;
1407 else if ((f [i] [i2] & 4) == 2) f [i] [i2] --;
1408 }
1409 for (i = 1; i < maxx; i += 3)
1410 for (i2 = 1; i2 < maxx; i2 += 3)
1411 if (isWater (f [i] [i2]))
1412 {
1413 if (f [i + 1] [i2] == GRASS) f [i + 1] [i2] = BUSHES1 + myrandom (3);
1414 if (f [i - 1] [i2] == GRASS) f [i - 1] [i2] = BUSHES1 + myrandom (3);
1415 if (f [i] [i2 + 1] == GRASS) f [i] [i2 + 1] = BUSHES1 + myrandom (3);
1416 if (f [i] [i2 - 1] == GRASS) f [i] [i2 - 1] = BUSHES1 + myrandom (3);
1417 }
1418 }
1419
1420
1421
1422 /****************************************************************************
1423 CREATE RIVERS
1424 ****************************************************************************/
1425
riverCheck(int x,int y,int * fl,int z,int z2)1426 bool Landscape::riverCheck (int x, int y, int *fl, int z, int z2)
1427 {
1428 if (x <= 0 || x >= maxx || y <= 0 || y >= maxx)
1429 return false;
1430 if (isType (f [x] [y], GRASS) || isWoods (f [x] [y]))
1431 {
1432 int bad = 0;
1433 for (int i = z; i <= z2; i ++)
1434 if (abs (fl [i * 2] - x) + abs (fl [i * 2 + 1] - y) <= 1)
1435 bad ++;
1436 if (bad <= 2) return true;
1437 }
1438 return false;
1439 }
1440
genRiver()1441 void Landscape::genRiver ()
1442 {
1443 bool ok, ok2;
1444 int lang;
1445 int i, i2, i3;
1446 int fl1 = 0, fl2 = 0, fl3 = 0, fl4 = 0, z, z2, xf, yf, xf2, yf2, h1, h2;
1447 int fl [400] [2];
1448 int abbruch;
1449 abbruch = 0;
1450 lang = 30;
1451 do
1452 {
1453 abbruch ++;
1454 do
1455 {
1456 xf = myrandom (maxx - 19) + 10; yf = myrandom (maxx - 19) + 10;
1457 }
1458 while (!isGround (yf, xf));
1459 fl [200] [0] = xf; fl [200] [1] = yf;
1460 xf2 = xf; yf2 = yf;
1461 z = 0; z2 = 0;
1462 do
1463 {
1464 h1 = 65535;
1465 ok = true;
1466 for (i = -1; i <= 1; i ++)
1467 for (i2 = -1; i2 <= 1; i2 ++)
1468 if (xf + i >= 0 && xf + i <= maxx &&
1469 yf + i2 >= 0 && yf + i2 <= maxx)
1470 if (riverCheck (xf + i, yf + i2, &fl [0] [0], 200 - z, 200 + z2))
1471 if (h [xf + i] [yf + i2] < h [xf] [yf])
1472 if (h [xf] [yf] - h [xf + i] [yf + i2] < h1)
1473 {
1474 h1 = h [xf] [yf] - h [xf + i] [yf + i2];
1475 fl1 = xf + i; fl2 = yf + i2;
1476 ok = false;
1477 }
1478 h2 = 65535;
1479 ok2 = true;
1480 for (i = -1; i <= 1; i ++)
1481 for (i2 = -1; i2 <= 1; i2 ++)
1482 if (xf2 + i >= 0 && xf2 + i <= maxx &&
1483 yf2 + i2 >= 0 && yf2 + i2 <= maxx)
1484 if (riverCheck (xf2 + i, yf2 + i2, &fl [0] [0], 200 - z, 200 + z2))
1485 if (h [xf2 + i] [yf2 + i2] > h [xf2] [yf2])
1486 if (h [xf2 + i] [yf2 + i2] - h [xf2] [yf2] < h2)
1487 {
1488 h2 = h [xf2 + i] [yf2 + i2] - h [xf2] [yf2];
1489 fl3 = xf2 + i; fl4 = yf2 + i2;
1490 ok2 = false;
1491 }
1492 if (!ok)
1493 {
1494 z ++;
1495 fl [200 - z] [0] = fl1; fl [200 - z] [1] = fl2;
1496 xf = fl1; yf = fl2;
1497 }
1498 if (!ok2)
1499 {
1500 z2 ++;
1501 fl [200 + z2] [0] = fl3; fl [200 + z2] [1] = fl4;
1502 xf2 = fl3; yf2 = fl4;
1503 }
1504 }
1505 while ((!ok || !ok2) && (z < 200) && (z2 < 200)); //ok and ok2 or (z >= 200) or (z2 >= 200);
1506 }
1507 while (z + z2 <= lang && abbruch <= 10); //until (z + z2 > lang) or (abbruch > 2000);
1508 if (abbruch <= 10)
1509 {
1510 if (z > 200) z = 200;
1511 if (z2 > 200) z2 = 200;
1512 for (i = 200 - z; i <= 200 + z2; i ++)
1513 {
1514 xf = fl [i] [0]; yf = fl [i] [1];
1515 f [xf] [yf] = SHALLOWWATER;
1516 if (isWater (f [xf] [yf]))
1517 {
1518 int hf = h [xf] [yf];
1519 for (i2 = -1; i2 <= 1; i2 ++)
1520 for (i3 = -1; i3 <= 1; i3 ++)
1521 if (xf + i2 >= 0 && xf + i2 <= maxx && yf + i3 >= 0 && yf + i3 < maxx)
1522 if (hf - h [xf + i2] [yf + i3] > 0
1523 && !isWater (f [xf + i2] [yf + i3]))
1524 {
1525 hf = h [xf + i2] [yf + i3];
1526 }
1527 hf -= 200;
1528 if (hf < 0) hf = 0;
1529 if (h [xf] [yf] - hf < 350)
1530 {
1531 f [xf] [yf] = SHALLOWWATER;
1532 }
1533 hw [xf] [yf] = h [xf] [yf];
1534 h [xf] [yf] = hf;
1535 }
1536 }
1537 }
1538 }
1539
1540
1541
1542 /****************************************************************************
1543 SEARCH PLANE TERRAIN STRUCTURE
1544 ****************************************************************************/
1545
1546 // divide map into 4x4 divisions and search plain in (divx,divy); (-1,-1) performs a global plain search
searchPlain(int divx,int divy,int * x,int * y)1547 void Landscape::searchPlain (int divx, int divy, int *x, int *y)
1548 {
1549 int i, i2;
1550 if (divx == -1 || divy == -1)
1551 {
1552 int val [MAXX_8] [MAXX_8];
1553 for (i = 8; i <= MAXX - 8; i += 8)
1554 for (i2 = 8; i2 <= MAXX - 8; i2 += 8)
1555 {
1556 if ((type != LAND_CANYON && f [i] [i2] == GRASS && f [i-4] [i2] == GRASS && f [i+4] [i2] == GRASS && f [i] [i2-4] == GRASS && f [i] [i2+4] == GRASS) ||
1557 (type == LAND_CANYON && f [i] [i2] == REDSAND && f [i-4] [i2] == REDSAND && f [i+4] [i2] == REDSAND && f [i] [i2-4] == REDSAND && f [i] [i2+4] == REDSAND))
1558 {
1559 if (type != 2)
1560 val [i >> 3] [i2 >> 3] = h [i] [i2] / 4;
1561 else
1562 val [i >> 3] [i2 >> 3] = 32000 - h [i] [i2] / 4;
1563 val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i-4] [i2]);
1564 val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i+4] [i2]);
1565 val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i] [i2-4]);
1566 val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i] [i2+4]);
1567 }
1568 else
1569 {
1570 val [i >> 3] [i2 >> 3] = 100000;
1571 }
1572 }
1573 int min = 100000;
1574 for (i = 1; i < MAXX_8; i ++)
1575 for (i2 = 1; i2 < MAXX_8; i2 ++)
1576 {
1577 if (val [i] [i2] < min)
1578 {
1579 min = val [i] [i2];
1580 *x = 8 * i;
1581 *y = 8 * i2;
1582 }
1583 }
1584 }
1585 else if (divx < DIVISIONS && divy < DIVISIONS)
1586 {
1587 int val [DIVX_8] [DIVX_8];
1588 for (i = 8 + divx * DIVX; i <= (divx + 1) * DIVX - 8; i += 8)
1589 for (i2 = 8 + divy * DIVX; i2 <= (divy + 1) * DIVX - 8; i2 += 8)
1590 {
1591 int ix = (i - 8 - divx * DIVX) >> 3;
1592 int iy = (i2 - 8 - divy * DIVX) >> 3;
1593 if (f [i] [i2] == GRASS && f [i-4] [i2] == GRASS && f [i+4] [i2] == GRASS && f [i] [i2-4] == GRASS && f [i] [i2+4] == GRASS)
1594 {
1595 val [ix] [iy] = abs (h [i] [i2] - h [i-4] [i2]);
1596 val [ix] [iy] += abs (h [i] [i2] - h [i+4] [i2]);
1597 val [ix] [iy] += abs (h [i] [i2] - h [i] [i2-4]);
1598 val [ix] [iy] += abs (h [i] [i2] - h [i] [i2+4]);
1599 val [ix] [iy] += h [i] [i2] / 250;
1600 }
1601 else
1602 {
1603 val [ix] [iy] = 100000;
1604 }
1605 }
1606 int min = 100000;
1607 for (i = 0; i < DIVX_8 - 1; i ++)
1608 for (i2 = 0; i2 < DIVX_8 - 1; i2 ++)
1609 {
1610 if (val [i] [i2] < min)
1611 {
1612 min = val [i] [i2];
1613 *x = 8 + 8 * i + divx * DIVX;
1614 *y = 8 + 8 * i2 + divy * DIVX;
1615 }
1616 }
1617 }
1618 }
1619
1620
1621
1622 /****************************************************************************
1623 CONSTRUCTOR
1624 ****************************************************************************/
1625
Landscape()1626 Landscape::Landscape ()
1627 {
1628 maxx = MAXX;
1629 n = LOG2SPLINE;
1630 maxn = LOG2MAXX;
1631 hoehe = HEIGHT * 256;
1632 for (int i = 0; i <= MAXX; i ++)
1633 for (int i2 = 0; i2 <= MAXX; i2 ++)
1634 {
1635 hw [i] [i2] = 0;
1636 h [i] [i2] = 0;
1637 f [i] [i2] = GRASS;
1638 }
1639 }
1640
~Landscape()1641 Landscape::~Landscape ()
1642 {
1643 }
1644
1645 #endif
1646