/* GL-117 Copyright 2001, 2002 Thomas A. Drexl aka heptargon This file is part of GL-117. GL-117 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GL-117 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GL-117; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This file includes a random landscape generator. */ #ifndef IS_LAND_H #include #include #include #include #include "land.h" #include "mathtab.h" /**************************************************************************** COMMON GLOBAL FUNCTIONS ****************************************************************************/ int Landscape::getCoord (int a) { return (a & MAXX_MASK); // return (a>=0)? a%MAXX : MAXX-a%MAXX; // more general version } /**************************************************************************** SMOOTING, CONVOLUTION, EROSION ****************************************************************************/ // fast Gaussian convolution (smoothing terrain) // H := height matrix, K := Gaussian kernel matrix // Let K := u conv v := (u^T)v, then H conv K = H conv (u conv v) = (H conv u) conv v void Landscape::convolveGauss (int radius, int hmin, int hmax) // only convolve height values in [hmin...hmax] { // create u and v vectors and restrict them to the interval [mincore...maxcore] float core_u [MAXCORE], core_v [MAXCORE]; int mincorex = 0, mincorey = 0, maxcorex = 0, maxcorey = 0; if (radius == 1) { core_u [4] = 0.25; core_u [5] = 0.5; core_u [6] = 0.25; core_v [4] = 0.25; core_v [5] = 0.5; core_v [6] = 0.25; mincorex = 4; maxcorex = 6; mincorey = 4; maxcorey = 6; } else if (radius == 2) { 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; 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; mincorex = 3; maxcorex = 7; mincorey = 3; maxcorey = 7; } else if (radius == 3) { 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; 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; mincorex = 2; maxcorex = 8; mincorey = 2; maxcorey = 8; } // do the convolutions int i, x, y, mx, my; float sum; float summe [MAXX + 1]; for (x = 0; x <= MAXX; x ++) summe [x] = 0; for (x = 0; x <= MAXX; x ++) { for (y = 0; y <= MAXX; y ++) // H conv u { summe [y] = 0; for (i = mincorex; i <= maxcorex; i ++) { mx = GETCOORD(x - MAXCORE / 2 + i); my = y; summe [y] += core_u [i] * h [mx] [my]; } } for (y = 0; y <= MAXX; y ++) // H conv v { if (h [x] [y] >= hmin && h [x] [y] <= hmax) // only convolve if current height in [hmin...hmax] { sum = 0; for (i = mincorey; i <= maxcorey; i ++) { my = GETCOORD(y - MAXCORE / 2 + i); sum += core_v [i] * summe [my]; } hg [x] [y] = (int) sum; } else { hg [x] [y] = h [x] [y]; } } } // copy hg back to h memcpy (h, hg, (MAXX+1) * (MAXX+1) * sizeof (unsigned short)); } // 'smooth' the glaciers using an erosion function void Landscape::smoothGlacier () { int i, i2; for (i = 0; i <= MAXX - 1; i ++) for (i2 = 0; i2 <= MAXX - 1; i2 ++) { if (f [i] [i2] == GLACIER) { int min = h[i][i2]; min = min < h[i+1][i2] ? min : h[i+1][i2]; min = min < h[i][i2+1] ? min : h[i][i2+1]; min = min < h[i+1][i2+1] ? min : h[i+1][i2+1]; h[i][i2] = min; } } } // Gaussian convolution for a single raster point (5x5) void Landscape::gauss (int x, int y) { if (x < 5) x = 5; else if (x > MAXX - 5) x = MAXX - 5; if (y < 5) y = 5; else if (y > MAXX - 5) y = MAXX - 5; int i, i2, i3, i4; int hmask [5] [5]; int g5[5][5]={{1,1,2,1,1}, {1,3,4,3,1}, {2,4,5,4,2}, {1,3,4,3,1}, {1,1,2,1,1}}; for (i = x-2; i <= x+2; i ++) for (i2 = y-2; i2 <= y+2; i2 ++) { int sum = 0; for (i3 = 0; i3 < 5; i3 ++) for (i4 = 0; i4 < 5; i4 ++) { sum += g5[i3][i4] * h[i+i3-2][i2+i4-2]; } sum /= 53; hmask [i-x+2] [i2-y+2] = sum; } for (i = x-2; i <= x+2; i ++) for (i2 = y-2; i2 <= y+2; i2 ++) { h[i][i2] = hmask[2][2]; hw[i][i2] = hmask[2][2]; } } // constant height for a single raster point (7x7) void Landscape::flatten (int x, int y, int dx, int dy) { int i, i2; if (x < dx) x = dx; else if (x > MAXX - dx) x = MAXX - dx; if (y < dy) y = dy; else if (y > MAXX - dy) y = MAXX - dy; for (i = x-dx; i <= x+dx; i ++) for (i2 = y-dy; i2 <= y+dy; i2 ++) { h[i][i2] = h[x][y]; hw[i][i2] = h[i][i2]; } } /**************************************************************************** LANDSCAPE TYPE QUERIES ****************************************************************************/ bool Landscape::isType (unsigned char type, unsigned char id) { return ((type & 0xFF) == (id << 0)); } bool Landscape::isWoods (int type) { type &= 0xFF; if (type >= CONIFEROUSWOODS0 && type <= BUSHES3) return true; return false; } bool Landscape::isWater (int type) { type &= 0xFF; if (type >= WATER && type <= XDEEPWATER) return true; return false; } bool Landscape::isGlacier (int type) { type &= 0xFF; if (type == GLACIER) return true; return false; } bool Landscape::isGround (int x, int y) { if (x < 0 || x > maxx || y < 0 || y > maxx) return false; int type = f [y] [x]; if (!isWater (type)) return true; return false; } /**************************************************************************** LANDSCAPE CREATION ****************************************************************************/ void Landscape::init () { int i, i2; for (i = 0; i <= maxx; i ++) for (i2 = 0; i2 <= maxx; i2 ++) { h [i] [i2] = 0; f [i] [i2] = 0; } } // cubic spline interpolation (obsolete -> Gaussian convolution) /* void interpolate (int n) { double s, r, q, a, b, c, d, e, f; int i, i2, i3, i4; long htest, p1, p2, p3, p4; i3 = n; i = 0; while (i <= maxx) { i2 = 0; while (i2 < maxx - (1 << i3)) { a = i2 + 1; b = i2 + (1 << i3) + 1; c = i2 + (1 << (i3 + 1)) + 1; d = h [(int) a - 1] [i]; e = h [(int) b - 1] [i]; f = h [(int) c - 1] [i]; double aq = a * a, bq = b * b, cq = c * c, mba = 1/b - 1/a, mca = 1/c - 1/a; s = ((f/cq-d/aq)/mca-(e/bq-d/aq)/mba)/((1/cq-1/aq)/mca-(1/bq-1/aq)/mba); r = ((e/bq-d/aq)/mba)-(1/bq-1/aq)/mba*s; q = d/aq - r/a - s/aq; for (i4 = (int) a + 1; i4 <= (int) c - 1; i4 ++) { if (i4 != b) { htest = (long) (i4 * i4 * q + i4 * r + s); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [i4 - 1] [i] == 0) { h [i4 - 1] [i] = h [i4 - 1] [i] + (int) (htest / 2); if (i4 - 1 < (1 << i3) || i4 - 1 > maxx - (1 << i3)) h [i4 - 1] [i] = h [i4 - 1] [i] * 2; } else { htest = htest / 2 + (htest - h [i4 - 1] [i] * 2) * (long) ((i4 - a) / (b - a) - 0.5); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; h [i4 - 1] [i] = h [i4 - 1] [i] + (int) htest; } } } i2 = i2 + (1 << i3); } i = i + (1 << i3); } i2 = 0; while (i2 <= maxx) { i = 0; while (i < maxx - (1 << i3)) { a = i + 1; b = i + (1 << i3) + 1; c = i + (1 << (i3 + 1)) + 1; d = h [i2] [(int) a - 1]; e = h [i2] [(int) b - 1]; f = h [i2] [(int) c - 1]; double aq = a * a, bq = b * b, cq = c * c, mba = 1/b - 1/a, mca = 1/c - 1/a; s = ((f/cq-d/aq)/mca-(e/bq-d/aq)/mba)/((1/cq-1/aq)/mca-(1/bq-1/aq)/mba); r = ((e/bq-d/aq)/mba)-(1/bq-1/aq)/mba*s; q = d/aq - r/a - s/aq; for (i4 = (int) a + 1; i4 <= (int) c - 1; i4 ++) { if (i4 != b) { htest = (long) (i4 * i4 * q + i4 * r + s); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [i2] [i4 - 1] == 0) { h [i2] [i4 - 1] = h [i2] [i4 - 1] + (int) (htest / 2); if (i4 - 1 < (1 << i3) || i4 - 1 > maxx - (1 << i3)) h [i2] [i4 - 1] = h [i2] [i4 - 1] * 2; } else { htest = htest / 2 + (htest - h [i2] [i4 - 1] * 2) * (long) ((i4 - a) / (b - a) - 0.5); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; h [i2] [i4 - 1] = h [i2] [i4 - 1] + (int) htest; } } } i = i + (1 << i3); } i2 ++; } }*/ void Landscape::genSurface (int hoehepc, int *heightmap) { int i, i2, x, y; int htest, h1, h2, step; type = LAND_ALPINE; hoehe = hoehepc * 512; init (); step = maxx / 4; if (heightmap == NULL) { for (i = 0; i < 4; i ++) for (i2 = 0; i2 < 4; i2 ++) if (h [i * step] [i2 * step] == 0) h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512); for (i = 0; i < 5; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } } else { step /= 2; n --; for (i = 0; i < 8; i ++) for (i2 = 0; i2 < 8; i2 ++) h [i * step] [i2 * step] = heightmap [i * 8 + i2]; for (i = 0; i < 9; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } } for (i = 2; i < n; i ++) { step = step / 2; y = 0; do { x = step; do { h1 = h [x - step] [y]; h2 = h [x + step] [y]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; x = x + 2 * step; } while (x != maxx + step); y = y + 2 * step; } while (y < maxx); for (x = step; x <= maxx - step; x += 2 * step) h [x] [maxx] = h [x] [0]; x = 0; do { y = step; do { h1 = h [x] [y - step]; h2 = h [x] [y + step]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; y = y + 2 * step; } while (y <= maxx); x = x + step; } while (x < maxx); for (y = step; y <= maxx - step; y += 2 * step) h [maxx] [y] = h [0] [y]; hoehe = (int) (hoehe / 1.1); } convolveGauss (2, 0, 35000); convolveGauss (1, 35001, 65535); highestpoint = 0; lowestpoint = 65535; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2]; if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2]; } } void Landscape::genErosionSurface (int hoehepc, int *heightmap) { int i, i2, x, y; int htest, h1, h2, step; type = LAND_ALPINE; hoehe = hoehepc * 512; init (); step = maxx / 4; if (heightmap == NULL) { for (i = 0; i < 4; i ++) for (i2 = 0; i2 < 4; i2 ++) if (h [i * step] [i2 * step] == 0) h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512); for (i = 0; i < 5; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } } else { step /= 2; n --; for (i = 0; i < 8; i ++) for (i2 = 0; i2 < 8; i2 ++) h [i * step] [i2 * step] = heightmap [i * 8 + i2]; for (i = 0; i < 9; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } } for (i = 2; i < n; i ++) { step = step / 2; y = 0; do { x = step; do { h1 = h [x - step] [y]; h2 = h [x + step] [y]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; x = x + 2 * step; } while (x != maxx + step); y = y + 2 * step; } while (y < maxx); for (x = step; x <= maxx - step; x += 2 * step) h [x] [maxx] = h [x] [0]; x = 0; do { y = step; do { h1 = h [x] [y - step]; h2 = h [x] [y + step]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; y = y + 2 * step; } while (y <= maxx); x = x + step; } while (x < maxx); for (y = step; y <= maxx - step; y += 2 * step) h [maxx] [y] = h [0] [y]; hoehe = (int) (hoehe / 1.1); } highestpoint = 0; lowestpoint = 65535; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2]; if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2]; } int erosion = (highestpoint - lowestpoint) / 5 + lowestpoint; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) if (h [i] [i2] < erosion) h [i] [i2] = erosion - 30 + myrandom (60, i, i2); convolveGauss (2, 0, 35000); convolveGauss (1, 35001, 65535); } void Landscape::genArcticSurface (int hoehepc, int *heightmap) { int i, i2, x, y; int htest, h1, h2, step; type = LAND_ARCTIC; hoehe = hoehepc * 512; init (); step = maxx / 4; if (heightmap == NULL) { for (i = 0; i < 4; i ++) for (i2 = 0; i2 < 4; i2 ++) if (h [i * step] [i2 * step] == 0) h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512); for (i = 0; i < 5; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } } else { step /= 2; n --; for (i = 0; i < 8; i ++) for (i2 = 0; i2 < 8; i2 ++) h [i * step] [i2 * step] = heightmap [i * 8 + i2]; for (i = 0; i < 9; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } } for (i = 2; i < n; i ++) { step = step / 2; y = 0; do { x = step; do { h1 = h [x - step] [y]; h2 = h [x + step] [y]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; x = x + 2 * step; } while (x != maxx + step); y = y + 2 * step; } while (y < maxx); for (x = step; x <= maxx - step; x += 2 * step) h [x] [maxx] = h [x] [0]; x = 0; do { y = step; do { h1 = h [x] [y - step]; h2 = h [x] [y + step]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; y = y + 2 * step; } while (y <= maxx); x = x + step; } while (x < maxx); for (y = step; y <= maxx - step; y += 2 * step) h [maxx] [y] = h [0] [y]; hoehe = (int) (hoehe / 1.1); } convolveGauss (2, 0, 35000); highestpoint = 0; lowestpoint = 65535; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2]; if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2]; f [i] [i2] = GLACIER; if (abs (h [i] [i2] - h [i + 1] [i2]) > 300) f [i] [i2] = ROCKS; if (abs (h [i] [i2] - h [i] [i2 + 1]) > 300) f [i] [i2] = ROCKS; if (h [i] [i2] < 32836 - hoehepc * 3) { int dh = 32836 - hoehepc * 3 - h [i] [i2]; if (dh < 2000) f [i] [i2] = SHALLOWWATER; else f [i] [i2] = DEEPWATER; hw [i] [i2] = 32836 - hoehepc * 3; } } } void Landscape::genMoonSurface (int height) { int i, i2, i3, x, y; int radius, rad, depth, depth2; double pi = 3.14; type = LAND_MOON; for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) h [i] [i2] = 30000 + myrandom (300, i, i2); int maxholes = 1; for (i = 0; i < maxholes; i ++) { x = myrandom (MAXX + 1); y = myrandom (MAXX + 1); radius = myrandom (50) + 200; depth = radius * height / 2; for (i2 = x - radius; i2 < x+radius; i2++) for (i3 = y - radius; i3 < y+radius; i3++) { rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3)); if (rad < radius) { if (rad < 0.67 * radius) { depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth); } else { depth2 = (int) (0.3 * sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1)); } h[getCoord(i2)][getCoord(i3)] -= depth2; } } } maxholes = myrandom (4) + 8 ; for (i = 0; i < maxholes; i++) { x = myrandom (MAXX + 1); y = myrandom (MAXX + 1); radius = myrandom (50) + 50; depth = radius * height / 2; for (i2 = x - radius; i2 < x+radius; i2++) for (i3 = y - radius; i3 < y+radius; i3++) { rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3)); if (rad < radius) { if (rad < 0.67 * radius) { depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth); } else { depth2 = (int) (0.3 * sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1)); } h[getCoord(i2)][getCoord(i3)] -= depth2; } } } maxholes = myrandom (10) + 20 ; for (i = 0; i < maxholes; i++) { x = myrandom (MAXX + 1); y = myrandom (MAXX + 1); radius = myrandom (20) + 20; depth = radius * height / 2; for (i2 = x - radius; i2 < x+radius; i2++) for (i3 = y - radius; i3 < y+radius; i3++) { rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3)); if (rad < radius) { if (rad < 0.67 * radius) { depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth); } else { depth2 = (int) (0.6 * sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1)); } h[getCoord(i2)][getCoord(i3)] -= depth2; } } } maxholes = myrandom (50) + 400; for (i = 0; i < maxholes; i++) { x = myrandom (MAXX + 1); y = myrandom (MAXX + 1); radius = myrandom (10) + 5; depth = radius * height / 3; for (i2 = x - radius; i2 < x+radius; i2++) for (i3 = y - radius; i3 < y+radius; i3++) { rad = (int) sqrt ((x-i2)*(x-i2)+(y-i3)*(y-i3)); if (rad < radius) { if (rad < 0.67 * radius) depth2 = (int) (cos ((float)rad / (2*radius/3) * pi/2) * depth); else depth2 = (int) (sin ((float)(radius - rad) / (radius / 3) * pi) * depth * (-1)); h[getCoord(i2)][getCoord(i3)] -= depth2; } } } convolveGauss (2, 0, 65535); } void Landscape::genCanyonSurface (int hoehepc) { int i, i2, x, y; int htest, h1, h2, step; type = LAND_CANYON; hoehe = hoehepc * 512; init (); step = maxx / 16; int minh = 0; int maxh = 127 * 256 + 64 * hoehe / 1024; for (i = 0; i < 16; i ++) for (i2 = 0; i2 < 16; i2 ++) if (h [i * step] [i2 * step] == 0) if (myrandom (2, i, i2)) h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024; else h [i * step] [i2 * step] = 127 * 256 + 64 * hoehe / 1024; for (i = 0; i < 17; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } for (i = 4; i < n; i ++) { step = step / 2; y = 0; do { x = step; do { h1 = h [x - step] [y]; h2 = h [x + step] [y]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < minh) htest = minh; if (htest > maxh) htest = maxh; if (h [x] [y] == 0) h [x] [y] = htest; x = x + 2 * step; } while (x != maxx + step); y = y + 2 * step; } while (y < maxx); for (x = step; x <= maxx - step; x += 2 * step) h [x] [maxx] = h [x] [0]; x = 0; do { y = step; do { h1 = h [x] [y - step]; h2 = h [x] [y + step]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < minh) htest = minh; if (htest > maxh) htest = maxh; if (h [x] [y] == 0) h [x] [y] = htest; y = y + 2 * step; } while (y <= maxx); x = x + step; } while (x < maxx); for (y = step; y <= maxx - step; y += 2 * step) h [maxx] [y] = h [0] [y]; hoehe = (int) (hoehe / 1.1); } for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) if (h [i] [i2] > 32836 - hoehepc * 30) h [i] [i2] -= h [i] [i2] % 2600; for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) f [i] [i2] = REDSTONE; convolveGauss (3, 0, 35000); convolveGauss (2, 35001, 65535); for (i = 0; i < MAXX; i ++) for (i2 = 0; i2 < MAXX; i2 ++) { if (abs (h [i] [i2] - h [i + 1] [i2]) < 200 && abs (h [i] [i2] - h [i] [i2 + 1]) < 200) { f [i] [i2] = REDSAND; if (h [i] [i2] > 30000 && !myrandom (80) && hoehepc > 20) f [i] [i2] = REDTREE0; } if (hoehepc > 20) { if (h [i] [i2] < 32836 - hoehepc * 40) { int dh = 32836 - hoehepc * 40 - h [i] [i2]; if (dh < 1500) f [i] [i2] = SHALLOWWATER; else f [i] [i2] = DEEPWATER; hw [i] [i2] = 32836 - hoehepc * 40; } } } highestpoint = 0; lowestpoint = 65535; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2]; if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2]; } } void Landscape::genDesertSurface (int hoehepc) { int i, i2, x, y; int htest, h1, h2, step; type = LAND_DESERT; hoehe = hoehepc * 512; init (); step = maxx / 16; for (i = 0; i < 16; i ++) for (i2 = 0; i2 < 16; i2 ++) if (h [i * step] [i2 * step] == 0) h [i * step] [i2 * step] = 127 * 256 - 64 * hoehe / 1024 + extremerandom (64 * hoehe / 512); for (i = 0; i < 17; i ++) { h [maxx] [i * step] = h [0] [i * step]; h [i * step] [maxx] = h [i * step] [0]; } for (i = 4; i < n; i ++) { step = step / 2; y = 0; do { x = step; do { h1 = h [x - step] [y]; h2 = h [x + step] [y]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; x = x + 2 * step; } while (x != maxx + step); y = y + 2 * step; } while (y < maxx); for (x = step; x <= maxx - step; x += 2 * step) h [x] [maxx] = h [x] [0]; x = 0; do { y = step; do { h1 = h [x] [y - step]; h2 = h [x] [y + step]; htest = ((h1 + h2) >> 1) - (128 >> i) * hoehe / 128 + myrandom ((128 >> i) * hoehe / 64, x, y); if (htest < 0) htest = 0; if (htest > 65535) htest = 65535; if (h [x] [y] == 0) h [x] [y] = htest; y = y + 2 * step; } while (y <= maxx); x = x + step; } while (x < maxx); for (y = step; y <= maxx - step; y += 2 * step) h [maxx] [y] = h [0] [y]; hoehe = (int) (hoehe / 1.5); } convolveGauss (2, 0, 65535); int i3; for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) { const int range = 11; int ha [range]; for (i3 = 0; i3 < range; i3 ++) ha [i3] = h [i] [GETCOORD(i2 + i3 - range / 2)]; int hmin = 65000, hmax = 0; for (i3 = 0; i3 < range; i3 ++) { if (ha [i3] < hmin) hmin = ha [i3]; if (ha [i3] > hmax) hmax = ha [i3]; } if (ha [range / 2 + 1] < ha [range / 2 - 1]) { hg [i] [i2] = hmin; } else { hg [i] [i2] = hmax; } } convolveGauss (2, 0, 65535); for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) h [i] [i2] = hg [i] [i2]; for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) f [i] [i2] = DESERTSAND; for (i = 0; i < MAXX; i += 4) for (i2 = 0; i2 < MAXX; i2 += 4) { if (!myrandom (50)) f [i] [i2] = CACTUS0; } highestpoint = 0; lowestpoint = 65535; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { if (h [i] [i2] > highestpoint) highestpoint = h [i] [i2]; if (h [i] [i2] < lowestpoint) lowestpoint = h [i] [i2]; } } void Landscape::genTrench (int width, int height) { int i, i2; int midleft = MAXX / 2 - width / 2, midright = MAXX / 2 + width / 2; int left = 0, right = 0; for (i = 0; i <= MAXX; i ++) { if (i != 148 && i != 52) { for (i2 = midleft + left; i2 < midright + right; i2 ++) { int height1 = height; if (i2 - midleft - left < 4) { height1 = height1 * (i2 - midleft - left) / 4; f [i] [i2] = REDSTONE; } if (i2 > midright + right - 4) { height1 = height1 * (midright + right - i2) / 4; f [i] [i2] = REDSTONE; } h [i] [i2] -= height1; } if (i & 1) { left += myrandom (5) - 2; right += myrandom (5) - 2; if (left < -5) left = -5; if (left > 5) left = 5; if (right < -5) right = -5; if (right > 5) right = 5; } } else { h [i] [MAXX / 2] -= height; } } lowestpoint -= height; } /**************************************************************************** CREATE ROCKS ****************************************************************************/ void Landscape::genRocks (int diffmin, int percent) { int i, i2, i3, i4, i5, d = 150; long hmin, hmax; long htest; double r, rd; rockborder = 65535; hmax = highestpoint; hmin = lowestpoint; if (hmax - hmin >= (long) diffmin * 256) // Generation for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { r = (hmax - hmin) / 100 * percent; rd = h [i] [i2]; rd = rd - h [i + 1] [i2] / 3 - h [i] [i2 + 1] / 3 - h [i + 1] [i2 + 1] / 3; rd = fabs (rd); int minrock = 0; if (percent > 50) minrock = (percent - 50) * 8; if (h [i] [i2] > hmax - r) { if (rd + minrock >= 800 - 800 * (h [i] [i2] - r) / (hmax - r)) { f [i] [i2] = ROCKS + myrandom (2); htest = h [i] [i2] - d + myrandom (d * 2); if (htest > 65535) htest = 65535; h [i] [i2] = (unsigned short) htest; if (h [i] [i2] < rockborder) rockborder = h [i] [i2]; } else if (rd + minrock >= 500 - 500 * (h [i] [i2] - r) / (hmax - r)) { f [i] [i2] = GRAVEL; } } if (abs (h [i] [i2] - h [i + 1] [i2]) >= 600 || abs (h [i] [i2] - h [i] [i2 + 1]) >= 600) { f [i] [i2] = ROCKS + myrandom (2); htest = h [i] [i2] - d + myrandom (d * 2); if (htest > 65535) htest = 65535; h [i] [i2] = (unsigned short) htest; } if (h [i] [i2] > hmax - r / 2) if (rd < 200 * (h [i] [i2] - r / 2) / (hmax - r / 2)) f [i] [i2] = GLACIER; } for (i = 1; i < maxx; i ++) // Lücken schließen for (i2 = 1; i2 < maxx; i2 ++) { if (f [i] [i2] != ROCKS) if (f [i - 1] [i2] == ROCKS && f [i + 1] [i2] == ROCKS || f [i] [i2 - 1] == ROCKS && f [i] [i2 + 1] == ROCKS) f [i] [i2] = ROCKS; if (f [i] [i2] != ROCKS) if (f [i - 1] [i2] == GLACIER && f [i + 1] [i2] == GLACIER || f [i] [i2 - 1] == GLACIER && f [i] [i2 + 1] == GLACIER) f [i] [i2] = GLACIER; } for (i = 1; i < maxx; i ++) // Felsengebiet uneben for (i2 = 1; i2 < maxx; i2 ++) if (f [i] [i2] == ROCKS) { i5 = 0; for (i3 = -1; i3 <= 1; i3 ++) for (i4 = -1; i4 <= 1; i4 ++) if (f [i + i3] [i2 + i4] == ROCKS) i5 ++; htest = (long) h [i] [i2] + (long) i5 * 50; if (htest > 65535) htest = 65535; h [i] [i2] = (unsigned short) htest; } smoothGlacier (); } /**************************************************************************** CREATE LAKES ****************************************************************************/ int Landscape::calcLake (int ys, int xs, unsigned short level, int num, int maxextent) { int i, i2, n, w, timeout = 0; bool hits; unsigned char sn = (unsigned char) num; int extent = 0; // h [xs] [ys] = level; w = 5; if (xs <= 0) xs = 1; if (ys <= 0) ys = 1; if (xs >= maxx) xs = maxx - 1; if (ys >= maxx) ys = maxx - 1; ftry [xs] [ys] = sn; do { timeout ++; i2 = 0; hits = false; while (i2 < maxx * 2) { i2 ++; n = i2; if (n > maxx) n = n - maxx * 2 + 1; for (i = xs; i < maxx; i ++) { if (ys - n >= 0 && ys - n < maxx) if (h [i] [ys - n] < level && ftry [i] [ys - n] != sn) if ((ftry [i - 1] [ys - n] == sn) || (ftry [i] [ys - n + 1] == sn) || (ftry [i + 1] [ys - n + 1] == sn) || (ftry [i - 1] [ys - n + 1] == sn)) { ftry [i] [ys - n] = sn; extent ++; hits = true; } if (ys + n > 0 && ys + n <= maxx) if (h [i] [ys + n] < level && ftry [i] [ys + n] != sn) if ((ftry [i - 1] [ys + n] == sn) || (ftry [i] [ys + n - 1] == sn) || (ftry [i + 1] [ys + n - 1] == sn) || (ftry [i - 1] [ys + n - 1] == sn)) { ftry [i] [ys + n] = sn; extent ++; hits = true; } } for (i = xs; i > 0; i --) { if (ys - n >= 0 && ys - n < maxx) if (h [i] [ys - n] < level && ftry [i] [ys - n] != sn) if ((ftry [i + 1] [ys - n] == sn) || (ftry [i] [ys - n + 1] == sn) || (ftry [i + 1] [ys - n + 1] == sn) || (ftry [i - 1] [ys - n + 1] == sn)) { ftry [i] [ys - n] = sn; extent ++; hits = true; } if (ys + n > 0 && ys + n <= maxx) if (h [i] [ys + n] < level && ftry [i] [ys + n] != sn) if ((ftry [i + 1] [ys + n] == sn) || (ftry [i] [ys + n - 1] == sn) || (ftry [i + 1] [ys + n - 1] == sn) || (ftry [i - 1] [ys + n - 1] == sn)) { ftry [i] [ys + n] = sn; extent ++; hits = true; } } for (i = ys; i < maxx; i ++) { if (xs - n >= 0 && xs - n < maxx) if (h [xs - n] [i] < level && ftry [xs - n] [i] != sn) if ((ftry [xs - n] [i - 1] == sn) || (ftry [xs - n + 1] [i] == sn) || (ftry [xs - n + 1] [i + 1] == sn) || (ftry [xs - n + 1] [i - 1] == sn)) { ftry [xs - n] [i] = sn; extent ++; hits = true; } if (xs + n > 0 && xs + n <= maxx) if (h [xs + n] [i] < level && ftry [xs + n] [i] != sn) if ((ftry [xs + n] [i - 1] == sn) || (ftry [xs + n - 1] [i] == sn) || (ftry [xs + n - 1] [i + 1] == sn) || (ftry [xs + n - 1] [i - 1] == sn)) { ftry [xs + n] [i] = sn; extent ++; hits = true; } } for (i = ys; i > 0; i --) { if (xs - n >= 0 && xs - n < maxx) if (h [xs - n] [i] < level && ftry [xs - n] [i] != sn) if ((ftry [xs - n] [i + 1] == sn) || (ftry [xs - n + 1] [i] == sn) || (ftry [xs - n + 1] [i + 1] == sn) || (ftry [xs - n + 1] [i - 1] == sn)) { ftry [xs - n] [i] = sn; extent ++; hits = true; } if (xs + n > 0 && xs + n <= maxx) if (h [xs + n] [i] < level && ftry [xs + n] [i] != sn) if ((ftry [xs + n] [i - 1] == sn) || (ftry [xs + n - 1] [i] == sn) || (ftry [xs + n - 1] [i + 1] == sn) || (ftry [xs + n - 1] [i - 1] == sn)) { ftry [xs + n] [i] = sn; extent ++; hits = true; } } } if (extent > maxextent) return -1; } while (hits && timeout < 10); if (timeout >= 10) return -1; return extent; } void Landscape::genLake (int depthpc) { for (int j = 0; j < 5; j ++) { int a1, i, i2; unsigned short level, zmin; int xs = 0, ys = 0; unsigned short depth = (highestpoint - lowestpoint) * depthpc / 100; zmin = 65535; int radius = MAXX * 2 * depthpc / 100; a1 = maxx / 8; for (i = 0; i < 20; i ++) { xs = myrandom (MAXX - 2 * a1) + a1; ys = myrandom (MAXX - 2 * a1) + a1; if (hw [ys] [xs] == 0) break; } if (i == 20) return; int minx = xs - radius, miny = ys - radius; int maxx = xs + radius, maxy = ys + radius; if (minx < 1) minx = 1; if (maxx > MAXX - 1) maxx = MAXX - 1; if (miny < 1) miny = 1; if (maxy > MAXX - 1) maxy = MAXX - 1; xs = -1; ys = -1; for (i = miny; i < maxy; i += 2) for (i2 = minx; i2 < maxx; i2 += 2) if (h [i] [i2] < zmin && hw [i] [i2] == 0) { zmin = h [i] [i2]; xs = i2; ys = i; } int extent = 0; if (xs >= 0) { level = zmin + depth; for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) { ftry [i] [i2] = GRASS; } extent = calcLake (xs, ys, level, TRYLAKE, radius * radius / 2); if (extent <= 0) break; for (i = 0; i <= MAXX; i ++) { if (ftry [i] [0] != ftry [i] [MAXX]) { if (ftry [i] [0] == TRYLAKE) extent += calcLake (MAXX, i, level, TRYLAKE, radius * radius / 2); else extent += calcLake (0, i, level, TRYLAKE, radius * radius / 2); if (extent <= 0) break; } } if (extent > 0) for (i = 0; i <= MAXX; i ++) { if (ftry [0] [i] != ftry [MAXX] [i]) { if (ftry [0] [i] == TRYLAKE) extent += calcLake (i, MAXX, level, TRYLAKE, radius * radius / 2); else extent += calcLake (i, 0, level, TRYLAKE, radius * radius / 2); if (extent <= 0) break; } } int waterlevel1 = 300; int waterlevel2 = 600; int waterlevel3 = 1400; int waterlevel4 = 2000; if (type == LAND_CANYON) { waterlevel1 = 400; waterlevel2 = 800; waterlevel3 = 1500; waterlevel4 = 2000; } for (i = 0; i <= MAXX; i ++) for (i2 = 0; i2 <= MAXX; i2 ++) if (ftry [i] [i2] == TRYLAKE) { ftry [i] [i2] = GRASS; if (level - h [i] [i2] < waterlevel1) f [i] [i2] = XSHALLOWWATER; else if (level - h [i] [i2] < waterlevel2) f [i] [i2] = SHALLOWWATER; else if (level - h [i] [i2] < waterlevel3) f [i] [i2] = WATER; else if (level - h [i] [i2] < waterlevel4) f [i] [i2] = DEEPWATER; else f [i] [i2] = XDEEPWATER; hw [i] [i2] = level; // + myrandom (w); } int barrage = ROCKS; for (i = 0; i <= MAXX; i ++) { if (hw [i] [0] != hw [i] [MAXX]) // error: water and landscape at different heights => make a barrage { if (hw [i] [0] == 0) { h [i] [MAXX - 2] = hw [i] [MAXX] + 100; h [i] [MAXX - 1] = hw [i] [MAXX] + 100; h [i] [MAXX] = h [i] [MAXX - 1]; h [i] [0] = h [i] [MAXX]; for (i2 = 1; i2 < 5; i2 ++) if (h [i] [i2] < h [i] [0] - i2 * 1000) { h [i] [i2] = h [i] [0] - i2 * 1000; f [i] [i2] = barrage; f [i] [i2 + 1] = barrage; } f [i] [MAXX - 2] = barrage; f [i] [MAXX - 1] = barrage; f [i] [MAXX] = barrage; f [i] [0] = barrage; f [i] [1] = barrage; } else if (hw [i] [MAXX] == 0) { h [i] [2] = hw [i] [0] + 100; h [i] [1] = hw [i] [0] + 100; h [i] [0] = h [i] [1]; h [i] [MAXX] = h [i] [0]; for (i2 = 1; i2 < 5; i2 ++) if (h [i] [MAXX - i2] < h [i] [MAXX] - i2 * 1000) { h [i] [MAXX - i2] = h [i] [MAXX] - i2 * 1000; f [i] [MAXX - i2] = barrage; f [i] [MAXX - i2 - 1] = barrage; } f [i] [2] = barrage; f [i] [1] = barrage; f [i] [0] = barrage; f [i] [MAXX] = barrage; f [i] [MAXX - 1] = barrage; } } if (hw [0] [i] != hw [MAXX] [i]) // error: water and landscape at different heights => make a barrage { if (hw [0] [i] == 0) { h [MAXX - 2] [i] = hw [MAXX] [i] + 100; h [MAXX - 1] [i] = hw [MAXX] [i] + 100; h [MAXX] [i] = h [MAXX - 1] [i]; h [0] [i] = h [MAXX] [i]; for (i2 = 1; i2 < 5; i2 ++) if (h [i2] [i] < h [0] [i] - i2 * 1000) { h [i2] [i] = h [0] [i] - i2 * 1000; f [i2] [i] = barrage; f [i2 + 1] [i] = barrage; } f [MAXX - 2] [i] = barrage; f [MAXX - 1] [i] = barrage; f [MAXX] [i] = barrage; f [0] [i] = barrage; f [1] [i] = barrage; } else if (hw [MAXX] [i] == 0) { h [2] [i] = hw [0] [i] + 100; h [1] [i] = hw [0] [i] + 100; h [0] [i] = h [1] [i]; h [MAXX] [i] = h [0] [i]; for (i2 = 1; i2 < 5; i2 ++) if (h [MAXX - i2] [i] < h [MAXX] [i] - i2 * 1000) { h [MAXX - i2] [i] = h [MAXX] [i] - i2 * 1000; f [MAXX - i2] [i] = barrage; f [MAXX - i2 - 1] [i] = barrage; } f [2] [i] = barrage; f [1] [i] = barrage; f [0] [i] = barrage; f [MAXX] [i] = barrage; f [MAXX - 1] [i] = barrage; } } } return; } } } /**************************************************************************** CREATE WOODS ****************************************************************************/ void Landscape::calcWoods (int dy) { int i, i2; int var = 2000; for (i = 0; i < maxx; i ++) for (i2 = 0; i2 < maxx; i2 ++) { if (fabs (h [i] [i2] - h [i + 1] [i2]) > dy) if (f [i] [i2] == 0) { int ra = myrandom (3); if (h [i] [i2] >= rockborder + 3000 + myrandom (var)) f [i] [i2] = (DWARFPINES1 + ra); else if (h [i] [i2] >= 15000 + myrandom (var) && h [i] [i2] < rockborder - 10000 + myrandom (var)) f [i] [i2] = (MIXEDWOODS1 + ra); else if (h [i] [i2] < 15000 + var) f [i] [i2] = (CONIFEROUSWOODS1 + ra); else f [i] [i2] = (DECIDUOUSWOODS1 + ra); } } for (i = 1; i < maxx; i ++) for (i2 = 1; i2 < maxx; i2 ++) if (f [i] [i2] == 0) if (isWoods (f [i - 1] [i2]) && isWoods (f [i + 1] [i2]) || isWoods (f [i] [i2 - 1]) && isWoods (f [i] [i2 + 1])) { int ra = myrandom (3); if (h [i] [i2] >= rockborder + 3000 + myrandom (var)) f [i] [i2] = (DWARFPINES1 + ra); else if (h [i] [i2] >= 15000 + myrandom (var) && h [i] [i2] < rockborder - 10000 + myrandom (var)) f [i] [i2] = (BUSHES1 + ra); else if (h [i] [i2] < 15000 + var) f [i] [i2] = (BUSHES1 + ra); else f [i] [i2] = (BUSHES1 + ra); } for (i = 4; i < maxx - 4; i ++) for (i2 = 4; i2 < maxx - 4; i2 ++) if (isWoods (f [i - 4] [i2]) && isWoods (f [i + 4] [i2]) && isWoods (f [i] [i2 - 4]) && isWoods (f [i] [i2 + 4]) && isWoods (f [i] [i2])) { f [i] [i2] --; } for (i = 1; i < maxx; i ++) for (i2 = 1; i2 < maxx; i2 ++) if (f [i] [i2] == f [i + 1] [i2] && f [i] [i2] == f [i - 1] [i2] && f [i] [i2] == f [i] [i2 + 1] && f [i] [i2] == f [i] [i2 - 1]) { if ((f [i] [i2] & 4) == 1) f [i] [i2] ++; else if ((f [i] [i2] & 4) == 2) f [i] [i2] --; } for (i = 1; i < maxx; i += 3) for (i2 = 1; i2 < maxx; i2 += 3) if (isWater (f [i] [i2])) { if (f [i + 1] [i2] == GRASS) f [i + 1] [i2] = BUSHES1 + myrandom (3); if (f [i - 1] [i2] == GRASS) f [i - 1] [i2] = BUSHES1 + myrandom (3); if (f [i] [i2 + 1] == GRASS) f [i] [i2 + 1] = BUSHES1 + myrandom (3); if (f [i] [i2 - 1] == GRASS) f [i] [i2 - 1] = BUSHES1 + myrandom (3); } } /**************************************************************************** CREATE RIVERS ****************************************************************************/ bool Landscape::riverCheck (int x, int y, int *fl, int z, int z2) { if (x <= 0 || x >= maxx || y <= 0 || y >= maxx) return false; if (isType (f [x] [y], GRASS) || isWoods (f [x] [y])) { int bad = 0; for (int i = z; i <= z2; i ++) if (abs (fl [i * 2] - x) + abs (fl [i * 2 + 1] - y) <= 1) bad ++; if (bad <= 2) return true; } return false; } void Landscape::genRiver () { bool ok, ok2; int lang; int i, i2, i3; int fl1 = 0, fl2 = 0, fl3 = 0, fl4 = 0, z, z2, xf, yf, xf2, yf2, h1, h2; int fl [400] [2]; int abbruch; abbruch = 0; lang = 30; do { abbruch ++; do { xf = myrandom (maxx - 19) + 10; yf = myrandom (maxx - 19) + 10; } while (!isGround (yf, xf)); fl [200] [0] = xf; fl [200] [1] = yf; xf2 = xf; yf2 = yf; z = 0; z2 = 0; do { h1 = 65535; ok = true; for (i = -1; i <= 1; i ++) for (i2 = -1; i2 <= 1; i2 ++) if (xf + i >= 0 && xf + i <= maxx && yf + i2 >= 0 && yf + i2 <= maxx) if (riverCheck (xf + i, yf + i2, &fl [0] [0], 200 - z, 200 + z2)) if (h [xf + i] [yf + i2] < h [xf] [yf]) if (h [xf] [yf] - h [xf + i] [yf + i2] < h1) { h1 = h [xf] [yf] - h [xf + i] [yf + i2]; fl1 = xf + i; fl2 = yf + i2; ok = false; } h2 = 65535; ok2 = true; for (i = -1; i <= 1; i ++) for (i2 = -1; i2 <= 1; i2 ++) if (xf2 + i >= 0 && xf2 + i <= maxx && yf2 + i2 >= 0 && yf2 + i2 <= maxx) if (riverCheck (xf2 + i, yf2 + i2, &fl [0] [0], 200 - z, 200 + z2)) if (h [xf2 + i] [yf2 + i2] > h [xf2] [yf2]) if (h [xf2 + i] [yf2 + i2] - h [xf2] [yf2] < h2) { h2 = h [xf2 + i] [yf2 + i2] - h [xf2] [yf2]; fl3 = xf2 + i; fl4 = yf2 + i2; ok2 = false; } if (!ok) { z ++; fl [200 - z] [0] = fl1; fl [200 - z] [1] = fl2; xf = fl1; yf = fl2; } if (!ok2) { z2 ++; fl [200 + z2] [0] = fl3; fl [200 + z2] [1] = fl4; xf2 = fl3; yf2 = fl4; } } while ((!ok || !ok2) && (z < 200) && (z2 < 200)); //ok and ok2 or (z >= 200) or (z2 >= 200); } while (z + z2 <= lang && abbruch <= 10); //until (z + z2 > lang) or (abbruch > 2000); if (abbruch <= 10) { if (z > 200) z = 200; if (z2 > 200) z2 = 200; for (i = 200 - z; i <= 200 + z2; i ++) { xf = fl [i] [0]; yf = fl [i] [1]; f [xf] [yf] = SHALLOWWATER; if (isWater (f [xf] [yf])) { int hf = h [xf] [yf]; for (i2 = -1; i2 <= 1; i2 ++) for (i3 = -1; i3 <= 1; i3 ++) if (xf + i2 >= 0 && xf + i2 <= maxx && yf + i3 >= 0 && yf + i3 < maxx) if (hf - h [xf + i2] [yf + i3] > 0 && !isWater (f [xf + i2] [yf + i3])) { hf = h [xf + i2] [yf + i3]; } hf -= 200; if (hf < 0) hf = 0; if (h [xf] [yf] - hf < 350) { f [xf] [yf] = SHALLOWWATER; } hw [xf] [yf] = h [xf] [yf]; h [xf] [yf] = hf; } } } } /**************************************************************************** SEARCH PLANE TERRAIN STRUCTURE ****************************************************************************/ // divide map into 4x4 divisions and search plain in (divx,divy); (-1,-1) performs a global plain search void Landscape::searchPlain (int divx, int divy, int *x, int *y) { int i, i2; if (divx == -1 || divy == -1) { int val [MAXX_8] [MAXX_8]; for (i = 8; i <= MAXX - 8; i += 8) for (i2 = 8; i2 <= MAXX - 8; i2 += 8) { 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) || (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)) { if (type != 2) val [i >> 3] [i2 >> 3] = h [i] [i2] / 4; else val [i >> 3] [i2 >> 3] = 32000 - h [i] [i2] / 4; val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i-4] [i2]); val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i+4] [i2]); val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i] [i2-4]); val [i >> 3] [i2 >> 3] += abs (h [i] [i2] - h [i] [i2+4]); } else { val [i >> 3] [i2 >> 3] = 100000; } } int min = 100000; for (i = 1; i < MAXX_8; i ++) for (i2 = 1; i2 < MAXX_8; i2 ++) { if (val [i] [i2] < min) { min = val [i] [i2]; *x = 8 * i; *y = 8 * i2; } } } else if (divx < DIVISIONS && divy < DIVISIONS) { int val [DIVX_8] [DIVX_8]; for (i = 8 + divx * DIVX; i <= (divx + 1) * DIVX - 8; i += 8) for (i2 = 8 + divy * DIVX; i2 <= (divy + 1) * DIVX - 8; i2 += 8) { int ix = (i - 8 - divx * DIVX) >> 3; int iy = (i2 - 8 - divy * DIVX) >> 3; 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) { val [ix] [iy] = abs (h [i] [i2] - h [i-4] [i2]); val [ix] [iy] += abs (h [i] [i2] - h [i+4] [i2]); val [ix] [iy] += abs (h [i] [i2] - h [i] [i2-4]); val [ix] [iy] += abs (h [i] [i2] - h [i] [i2+4]); val [ix] [iy] += h [i] [i2] / 250; } else { val [ix] [iy] = 100000; } } int min = 100000; for (i = 0; i < DIVX_8 - 1; i ++) for (i2 = 0; i2 < DIVX_8 - 1; i2 ++) { if (val [i] [i2] < min) { min = val [i] [i2]; *x = 8 + 8 * i + divx * DIVX; *y = 8 + 8 * i2 + divy * DIVX; } } } } /**************************************************************************** CONSTRUCTOR ****************************************************************************/ Landscape::Landscape () { maxx = MAXX; n = LOG2SPLINE; maxn = LOG2MAXX; hoehe = HEIGHT * 256; for (int i = 0; i <= MAXX; i ++) for (int i2 = 0; i2 <= MAXX; i2 ++) { hw [i] [i2] = 0; h [i] [i2] = 0; f [i] [i2] = GRASS; } } Landscape::~Landscape () { } #endif