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