From d5b6353493868ac14b277155f398bd87f08c484c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 2 Nov 2014 16:36:59 +0100 Subject: Grown biomes: Unified with GrownProt biomes. Also fixed a Zoom filter randomness. --- src/Generating/IntGen.h | 567 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 484 insertions(+), 83 deletions(-) (limited to 'src/Generating/IntGen.h') diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 15a5c9157..83a0e569a 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -167,7 +167,7 @@ public: for (int x = 0; x < SizeX; x++) { int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); - a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; + a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0; } } @@ -186,6 +186,9 @@ protected: +/** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between. +This means that the zoome out image is randomly distorted. Applying zoom several times provides all +the distortion that the generators need. */ template class cIntGenZoom : public cIntGenWithNoise @@ -212,31 +215,30 @@ public: // Generate the underlying data with half the resolution: int lowerMinX = a_MinX >> 1; int lowerMinZ = a_MinZ >> 1; - int Underlying[m_LowerSizeX * m_LowerSizeZ]; - m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, Underlying); + int lowerData[m_LowerSizeX * m_LowerSizeZ]; + m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerData); const int lowStepX = (m_LowerSizeX - 1) * 2; const int lowStepZ = (m_LowerSizeZ - 1) * 2; - int Cache[lowStepX * lowStepZ]; + int cache[lowStepX * lowStepZ]; // Discreet-interpolate the values into twice the size: for (int z = 0; z < m_LowerSizeZ - 1; ++z) { int idx = (z * 2) * lowStepX; - int PrevZ0 = Underlying[z * m_LowerSizeX]; - int PrevZ1 = Underlying[(z + 1) * m_LowerSizeX]; + int PrevZ0 = lowerData[z * m_LowerSizeX]; + int PrevZ1 = lowerData[(z + 1) * m_LowerSizeX]; for (int x = 0; x < m_LowerSizeX - 1; ++x) { - int ValX1Z0 = Underlying[x + 1 + z * m_LowerSizeX]; - int ValX1Z1 = Underlying[x + 1 + (z + 1) * m_LowerSizeX]; + int ValX1Z0 = lowerData[x + 1 + z * m_LowerSizeX]; + int ValX1Z1 = lowerData[x + 1 + (z + 1) * m_LowerSizeX]; int RndX = (x + lowerMinX) * 2; int RndZ = (z + lowerMinZ) * 2; - Cache[idx] = PrevZ0; - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); - idx++; - Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); - idx++; + cache[idx] = PrevZ0; + cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1); + cache[idx + 1] = super::ChooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0); + cache[idx + 1 + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } @@ -245,7 +247,7 @@ public: // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: for (int z = 0; z < SizeZ; ++z) { - memcpy(a_Values + z * SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int)); + memcpy(a_Values + z * SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int)); } } @@ -257,16 +259,18 @@ protected: +/** Smoothes out some artifacts generated by the zooming - mostly single-pixel values. +Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */ template class cIntGenSmooth : public cIntGenWithNoise { typedef cIntGenWithNoise super; - static const int UnderlyingSizeX = SizeX + 2; - static const int UnderlyingSizeZ = SizeZ + 2; + static const int m_LowerSizeX = SizeX + 2; + static const int m_LowerSizeZ = SizeZ + 2; public: - typedef std::shared_ptr> Underlying; + typedef std::shared_ptr> Underlying; cIntGenSmooth(int a_Seed, Underlying a_Underlying) : @@ -279,8 +283,8 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying values: - int Cache[UnderlyingSizeX * UnderlyingSizeZ]; - m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + int lowerData[m_LowerSizeX * m_LowerSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerData); // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. // Also get rid of single-pixel irregularities (A-B-A): @@ -289,33 +293,33 @@ public: int NoiseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { - int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; - int Above = Cache[x + 1 + z * UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; + int val = lowerData[x + 1 + (z + 1) * m_LowerSizeX]; + int above = lowerData[x + 1 + z * m_LowerSizeX]; + int below = lowerData[x + 1 + (z + 2) * m_LowerSizeX]; + int left = lowerData[x + (z + 1) * m_LowerSizeX]; + int right = lowerData[x + 2 + (z + 1) * m_LowerSizeX]; - if ((Left == Right) && (Above == Below)) + if ((left == right) && (above == below)) { if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) { - val = Left; + val = left; } else { - val = Above; + val = above; } } else { - if (Left == Right) + if (left == right) { - val = Left; + val = left; } - if (Above == Below) + if (above == below) { - val = Above; + val = above; } } @@ -332,7 +336,8 @@ protected: -template +/** Converts land biomes at the edge of an ocean into the respective beach biome. */ +template class cIntGenBeaches : public cIntGen { @@ -398,23 +403,24 @@ public: }; // Generate the underlying values: - int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; - m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); // Add beaches between ocean and biomes: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { - int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; - int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; + int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int above = lowerValues[x + 1 + z * m_UnderlyingSizeX]; + int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX]; + int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX]; if (!IsBiomeOcean(val)) { - if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right)) { + // First convert the value to a regular biome (drop the M flag), then modulo by our biome count: val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; } } @@ -431,7 +437,8 @@ protected: -/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +/** Generates the underlying numbers and then randomly changes some ocean group pixels into random land +biome group pixels, based on the predefined chance. */ template class cIntGenAddIslands : public cIntGenWithNoise @@ -442,9 +449,9 @@ public: typedef std::shared_ptr> Underlying; - cIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + cIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying) : super(a_Seed), - m_Threshold(a_Threshold), + m_Chance(a_Chance), m_Underlying(a_Underlying) { } @@ -460,17 +467,18 @@ public: if (a_Values[x + z * SizeX] == bgOcean) { int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; - if (rnd % 100 < m_Threshold) + if (rnd % 1000 < m_Chance) { - a_Values[x + z * SizeX] = (rnd / 100) % bgLandOceanMax; + a_Values[x + z * SizeX] = (rnd / 1003) % bgLandOceanMax; } } - } - } + } // for x + } // for z } protected: - int m_Threshold; + /** Chance, in permille, of an island being generated in ocean. */ + int m_Chance; Underlying m_Underlying; }; @@ -502,32 +510,32 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) { // Generate the underlying biome groups: - int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; - m_Underlying->GetInts(a_MinX, a_MinZ, Cache); + int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX, a_MinZ, lowerValues); // Change the biomes on incompatible edges into an edge biome: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { - int v = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; - int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; - switch (v) + int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int above = lowerValues[x + 1 + z * m_UnderlyingSizeX]; + int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX]; + int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX]; + switch (val) { // Desert should neighbor only oceans, desert and temperates; change to temperate when another: case bgDesert: { if ( - !isDesertCompatible(Above) || - !isDesertCompatible(Below) || - !isDesertCompatible(Left) || - !isDesertCompatible(Right) + !isDesertCompatible(above) || + !isDesertCompatible(below) || + !isDesertCompatible(left) || + !isDesertCompatible(right) ) { - v = bgTemperate; + val = bgTemperate; } break; } // case bgDesert @@ -536,18 +544,18 @@ public: case bgIce: { if ( - (Above == bgDesert) || - (Below == bgDesert) || - (Left == bgDesert) || - (Right == bgDesert) + (above == bgDesert) || + (below == bgDesert) || + (left == bgDesert) || + (right == bgDesert) ) { - v = bgTemperate; + val = bgTemperate; } break; } // case bgIce } - a_Values[x + z * SizeX] = v; + a_Values[x + z * SizeX] = val; } // for x } // for z } @@ -578,6 +586,9 @@ protected: +/** Turns biome group indices into real biomes. +For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with +that biome. */ template class cIntGenBiomes : public cIntGenWithNoise @@ -600,7 +611,13 @@ public: // Define the per-biome-group biomes: static const int oceanBiomes[] = { - biOcean, // biDeepOcean, + biOcean, // biDeepOcean, + }; + + // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) + static const int rareOceanBiomes[] = + { + biOcean, }; static const int desertBiomes[] = @@ -608,19 +625,29 @@ public: biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; + static const int rareDesertBiomes[] = + { + biMesaPlateau, biMesaPlateauF, + }; + static const int temperateBiomes[] = { biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; + static const int rareTemperateBiomes[] = + { + biJungle, // Jungle is not strictly temperate, but let's piggyback it here + }; + static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; - static const int jungleBiomes[] = + static const int rareMountainBiomes[] = { - biJungle, biJungle, biJungle, biForest, + biMegaTaiga, }; static const int iceBiomes[] = @@ -628,20 +655,28 @@ public: biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const int mesaBiomes[] = + // Same as iceBiomes, there's no rare ice biome + static const int rareIceBiomes[] = { - biMesa, biMesaPlateau, + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const cBiomesInGroups BiomesInGroups[] = + static const cBiomesInGroups biomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, - /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, - /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, + }; + + static const cBiomesInGroups rareBiomesInGroups[] = + { + /* bgOcean */ { static_cast(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes}, }; // Generate the underlying values, representing biome groups: @@ -654,7 +689,9 @@ public: for (int x = 0; x < SizeX; x++) { int val = a_Values[x + IdxZ]; - const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + const cBiomesInGroups & Biomes = (val > bgfRare) ? + rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] : + biomesInGroups[val % ARRAYCOUNT(biomesInGroups)]; int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } @@ -678,6 +715,7 @@ protected: +/** Randomly replaces pixels of one value to another value, using the given chance. */ template class cIntGenReplaceRandomly : public cIntGenWithNoise @@ -713,7 +751,7 @@ public: if (a_Values[idx] == m_From) { int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; - if (rnd % 100 < m_Chance) + if (rnd % 1000 < m_Chance) { a_Values[idx] = m_To; } @@ -724,9 +762,15 @@ public: protected: + /** The original value to be replaced. */ int m_From; + + /** The destination value to which to replace. */ int m_To; + + /** Chance, in permille, of replacing the value. */ int m_Chance; + Underlying m_Underlying; }; @@ -735,7 +779,9 @@ protected: /** Mixer that joins together finalized biomes and rivers. -It first checks for oceans; if there's no ocean, it checks for a river. */ +It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean. +If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either +regular river or frozen river, based on the biome. */ template class cIntGenMixRivers: public cIntGen @@ -757,8 +803,8 @@ public: { // Generate the underlying data: m_Biomes->GetInts(a_MinX, a_MinZ, a_Values); - typename super::Values Rivers; - m_Rivers->GetInts(a_MinX, a_MinZ, Rivers); + typename super::Values riverData; + m_Rivers->GetInts(a_MinX, a_MinZ, riverData); // Mix the values: for (int z = 0; z < SizeZ; z++) @@ -772,7 +818,7 @@ public: // Oceans are kept without any changes continue; } - if (Rivers[idx] != biRiver) + if (riverData[idx] != biRiver) { // There's no river, keep the current value continue; @@ -925,7 +971,10 @@ public: } // If at least 3 ocean neighbors and the chance is right, change: - if ((NumOceanNeighbors >= 3) && ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance)) + if ( + (NumOceanNeighbors >= 3) && + ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance) + ) { a_Values[x + z * SizeX] = m_ToValue; } @@ -1003,3 +1052,355 @@ protected: + +/** Adds a "rare" flag to random biome groups, based on the given chance. */ +template +class cIntGenRareBiomeGroups: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + + // Change some of the biome groups into rare biome groups: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + int idx = x + SizeX * z; + a_Values[idx] = a_Values[idx] | bgfRare; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel into the rare biome group. */ + int m_Chance; + + /** The underlying generator. */ + Underlying m_Underlying; +}; + + + + + +/** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places +that have their alterations set. */ +template +class cIntGenAlternateBiomes: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes): + super(a_Seed), + m_Alterations(a_Alterations), + m_BaseBiomes(a_BaseBiomes) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the base biomes and the alterations: + m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_Values); + super::Values alterations; + m_Alterations->GetInts(a_MinX, a_MinZ, alterations); + + // Change the biomes into their alternate versions: + for (int idx = 0; idx < SizeX * SizeZ; ++idx) + { + if (alterations[idx] == 0) + { + // No change + continue; + } + + // Change to alternate biomes: + int val = a_Values[idx]; + switch (val) + { + case biBirchForest: val = biBirchForestHills; break; + case biDesert: val = biDesertHills; break; + case biExtremeHills: val = biExtremeHillsPlus; break; + case biForest: val = biForestHills; break; + case biIcePlains: val = biIceMountains; break; + case biJungle: val = biJungleHills; break; + case biMegaTaiga: val = biMegaTaigaHills; break; + case biMesaPlateau: val = biMesa; break; + case biMesaPlateauF: val = biMesa; break; + case biMesaPlateauM: val = biMesa; break; + case biMesaPlateauFM: val = biMesa; break; + case biPlains: val = biForest; break; + case biRoofedForest: val = biPlains; break; + case biSavanna: val = biSavannaPlateau; break; + case biTaiga: val = biTaigaHills; break; + } + a_Values[idx] = val; + } // for idx - a_Values[] + } + +protected: + Underlying m_Alterations; + Underlying m_BaseBiomes; +}; + + + + + +/** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */ +template +class cIntGenBiomeEdges: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + static const int m_LowerSizeX = SizeX + 2; + static const int m_LowerSizeZ = SizeZ + 2; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenBiomeEdges(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying biomes: + Underlying::element_type::Values lowerValues; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); + + // Convert incompatible edges into neutral biomes: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int biome = lowerValues[x + 1 + (z + 1) * m_LowerSizeX]; + int above = lowerValues[x + 1 + z * m_LowerSizeX]; + int below = lowerValues[x + 1 + (z + 2) * m_LowerSizeX]; + int left = lowerValues[x + (z + 1) * m_LowerSizeX]; + int right = lowerValues[x + 2 + (z + 1) * m_LowerSizeX]; + + switch (biome) + { + case biDesert: + case biDesertM: + case biDesertHills: + { + if ( + IsBiomeVeryCold(static_cast(above)) || + IsBiomeVeryCold(static_cast(below)) || + IsBiomeVeryCold(static_cast(left)) || + IsBiomeVeryCold(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // case biDesert + + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + { + if ( + !isMesaCompatible(above) || + !isMesaCompatible(below) || + !isMesaCompatible(left) || + !isMesaCompatible(right) + ) + { + biome = biDesert; + } + break; + } // Mesa biomes + + case biJungle: + case biJungleM: + { + if ( + !isJungleCompatible(above) || + !isJungleCompatible(below) || + !isJungleCompatible(left) || + !isJungleCompatible(right) + ) + { + biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM; + } + break; + } // Jungle biomes + + case biSwampland: + case biSwamplandM: + { + if ( + IsBiomeNoDownfall(static_cast(above)) || + IsBiomeNoDownfall(static_cast(below)) || + IsBiomeNoDownfall(static_cast(left)) || + IsBiomeNoDownfall(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // Swampland biomes + } // switch (biome) + + a_Values[x + z * SizeX] = biome; + } // for x + } // for z + } + + +protected: + Underlying m_Underlying; + + + bool isMesaCompatible(int a_Biome) + { + switch (a_Biome) + { + case biDesert: + case biMesa: + case biMesaBryce: + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + case biOcean: + case biDeepOcean: + { + return true; + } + default: + { + return false; + } + } + } + + + bool isJungleCompatible(int a_Biome) + { + switch (a_Biome) + { + case biJungle: + case biJungleM: + case biJungleEdge: + case biJungleEdgeM: + case biJungleHills: + { + return true; + } + default: + { + return false; + } + } + } +}; + + + + + +/** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that +have their alterations set. */ +template +class cIntGenMBiomes: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying), + m_Alteration(a_Alteration) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying biomes and the alterations: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + super::Values alterations; + m_Alteration->GetInts(a_MinX, a_MinZ, alterations); + + // Wherever alterations are nonzero, change into alternate biome, if available: + for (int idx = 0; idx < SizeX * SizeZ; ++idx) + { + if (alterations[idx] == 0) + { + continue; + } + + // Ice spikes biome was removed from here, because it was generated way too often + switch (a_Values[idx]) + { + case biPlains: a_Values[idx] = biSunflowerPlains; break; + case biDesert: a_Values[idx] = biDesertM; break; + case biExtremeHills: a_Values[idx] = biExtremeHillsM; break; + case biForest: a_Values[idx] = biFlowerForest; break; + case biTaiga: a_Values[idx] = biTaigaM; break; + case biSwampland: a_Values[idx] = biSwamplandM; break; + case biJungle: a_Values[idx] = biJungleM; break; + case biJungleEdge: a_Values[idx] = biJungleEdgeM; break; + case biBirchForest: a_Values[idx] = biBirchForestM; break; + case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break; + case biRoofedForest: a_Values[idx] = biRoofedForestM; break; + case biColdTaiga: a_Values[idx] = biColdTaigaM; break; + case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break; + case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break; + case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break; + case biSavanna: a_Values[idx] = biSavannaM; break; + case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break; + case biMesa: a_Values[idx] = biMesaBryce; break; + case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break; + case biMesaPlateau: a_Values[idx] = biMesaBryce; break; + } + } // for idx - a_Values[] / alterations[] + } + +protected: + Underlying m_Underlying; + Underlying m_Alteration; +}; + + + + -- cgit v1.2.3