Biome API: Add per-biome riverbed material and depth
[oweals/minetest.git] / src / mapgen_valleys.cpp
1 /*
2 Minetest Valleys C
3 Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4 Copyright (C) 2010-2015 paramat, Matt Gregory
5 Copyright (C) 2016 Duane Robertson <duane@duanerobertson.com>
6
7 Based on Valleys Mapgen by Gael de Sailly
8  (https://forum.minetest.net/viewtopic.php?f=9&t=11430)
9 and mapgen_v7, mapgen_flat by kwolekr and paramat.
10
11 Licensing changed by permission of Gael de Sailly.
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 2.1 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public License along
24 with this program; if not, write to the Free Software Foundation, Inc.,
25 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 */
27
28 #include "mapgen.h"
29 #include "voxel.h"
30 #include "noise.h"
31 #include "mapblock.h"
32 #include "mapnode.h"
33 #include "map.h"
34 #include "content_sao.h"
35 #include "nodedef.h"
36 #include "voxelalgorithms.h"
37 #include "settings.h" // For g_settings
38 #include "emerge.h"
39 #include "dungeongen.h"
40 #include "treegen.h"
41 #include "mg_biome.h"
42 #include "mg_ore.h"
43 #include "mg_decoration.h"
44 #include "mapgen_valleys.h"
45 #include "cavegen.h"
46
47
48 //#undef NDEBUG
49 //#include "assert.h"
50
51 //#include "util/timetaker.h"
52 //#include "profiler.h"
53
54
55 //static Profiler mapgen_prof;
56 //Profiler *mapgen_profiler = &mapgen_prof;
57
58 static FlagDesc flagdesc_mapgen_valleys[] = {
59         {"altitude_chill", MGVALLEYS_ALT_CHILL},
60         {"humid_rivers",   MGVALLEYS_HUMID_RIVERS},
61         {NULL,             0}
62 };
63
64 ///////////////////////////////////////////////////////////////////////////////
65
66
67 MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
68         : MapgenBasic(mapgenid, params, emerge)
69 {
70         // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
71         this->m_bgen = (BiomeGenOriginal *)biomegen;
72
73         this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
74                         g_settings->getU16("map_generation_limit"));
75
76         MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
77         BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
78
79         this->spflags            = sp->spflags;
80         this->altitude_chill     = sp->altitude_chill;
81         this->large_cave_depth   = sp->large_cave_depth;
82         this->lava_features_lim  = rangelim(sp->lava_features, 0, 10);
83         this->massive_cave_depth = sp->massive_cave_depth;
84         this->river_depth_bed    = sp->river_depth + 1.f;
85         this->river_size_factor  = sp->river_size / 100.f;
86         this->water_features_lim = rangelim(sp->water_features, 0, 10);
87         this->cave_width         = sp->cave_width;
88
89         //// 2D Terrain noise
90         noise_filler_depth       = new Noise(&sp->np_filler_depth,       seed, csize.X, csize.Z);
91         noise_inter_valley_slope = new Noise(&sp->np_inter_valley_slope, seed, csize.X, csize.Z);
92         noise_rivers             = new Noise(&sp->np_rivers,             seed, csize.X, csize.Z);
93         noise_terrain_height     = new Noise(&sp->np_terrain_height,     seed, csize.X, csize.Z);
94         noise_valley_depth       = new Noise(&sp->np_valley_depth,       seed, csize.X, csize.Z);
95         noise_valley_profile     = new Noise(&sp->np_valley_profile,     seed, csize.X, csize.Z);
96
97         //// 3D Terrain noise
98         // 1-up 1-down overgeneration
99         noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
100         // 1-down overgeneraion
101         noise_cave1             = new Noise(&sp->np_cave1,             seed, csize.X, csize.Y + 1, csize.Z);
102         noise_cave2             = new Noise(&sp->np_cave2,             seed, csize.X, csize.Y + 1, csize.Z);
103         noise_massive_caves     = new Noise(&sp->np_massive_caves,     seed, csize.X, csize.Y + 1, csize.Z);
104
105         this->humid_rivers       = (spflags & MGVALLEYS_HUMID_RIVERS);
106         this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
107         this->humidity_adjust    = bp->np_humidity.offset - 50.f;
108
109         // a small chance of overflows if the settings are very high
110         this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
111         this->lava_max_height       = water_level + MYMAX(0, lava_features_lim - 4) * 50;
112
113         tcave_cache = new float[csize.Y + 2];
114
115         // Resolve content to be used
116         c_lava_source = ndef->getId("mapgen_lava_source");
117 }
118
119
120 MapgenValleys::~MapgenValleys()
121 {
122         delete noise_cave1;
123         delete noise_cave2;
124         delete noise_filler_depth;
125         delete noise_inter_valley_fill;
126         delete noise_inter_valley_slope;
127         delete noise_rivers;
128         delete noise_massive_caves;
129         delete noise_terrain_height;
130         delete noise_valley_depth;
131         delete noise_valley_profile;
132
133         delete[] tcave_cache;
134 }
135
136
137 MapgenValleysParams::MapgenValleysParams()
138 {
139         spflags            = MGVALLEYS_HUMID_RIVERS | MGVALLEYS_ALT_CHILL;
140         altitude_chill     = 90; // The altitude at which temperature drops by 20C.
141         large_cave_depth   = -33;
142         lava_features      = 0;  // How often water will occur in caves.
143         massive_cave_depth = -256;  // highest altitude of massive caves
144         river_depth        = 4;  // How deep to carve river channels.
145         river_size         = 5;  // How wide to make rivers.
146         water_features     = 0;  // How often water will occur in caves.
147         cave_width         = 0.3;
148
149         np_cave1              = NoiseParams(0,     12,   v3f(96,   96,   96),   52534, 4, 0.5,   2.0);
150         np_cave2              = NoiseParams(0,     12,   v3f(96,   96,   96),   10325, 4, 0.5,   2.0);
151         np_filler_depth       = NoiseParams(0.f,   1.2f, v3f(256,  256,  256),  1605,  3, 0.5f,  2.f);
152         np_inter_valley_fill  = NoiseParams(0.f,   1.f,  v3f(256,  512,  256),  1993,  6, 0.8f,  2.f);
153         np_inter_valley_slope = NoiseParams(0.5f,  0.5f, v3f(128,  128,  128),  746,   1, 1.f,   2.f);
154         np_rivers             = NoiseParams(0.f,   1.f,  v3f(256,  256,  256),  -6050, 5, 0.6f,  2.f);
155         np_massive_caves      = NoiseParams(0.f,   1.f,  v3f(768,  256,  768),  59033, 6, 0.63f, 2.f);
156         np_terrain_height     = NoiseParams(-10.f, 50.f, v3f(1024, 1024, 1024), 5202,  6, 0.4f,  2.f);
157         np_valley_depth       = NoiseParams(5.f,   4.f,  v3f(512,  512,  512),  -1914, 1, 1.f,   2.f);
158         np_valley_profile     = NoiseParams(0.6f,  0.5f, v3f(512,  512,  512),  777,   1, 1.f,   2.f);
159 }
160
161
162 void MapgenValleysParams::readParams(const Settings *settings)
163 {
164         settings->getFlagStrNoEx("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys);
165         settings->getU16NoEx("mgvalleys_altitude_chill",     altitude_chill);
166         settings->getS16NoEx("mgvalleys_large_cave_depth",   large_cave_depth);
167         settings->getU16NoEx("mgvalleys_lava_features",      lava_features);
168         settings->getS16NoEx("mgvalleys_massive_cave_depth", massive_cave_depth);
169         settings->getU16NoEx("mgvalleys_river_depth",        river_depth);
170         settings->getU16NoEx("mgvalleys_river_size",         river_size);
171         settings->getU16NoEx("mgvalleys_water_features",     water_features);
172         settings->getFloatNoEx("mgvalleys_cave_width",       cave_width);
173
174         settings->getNoiseParams("mgvalleys_np_cave1",              np_cave1);
175         settings->getNoiseParams("mgvalleys_np_cave2",              np_cave2);
176         settings->getNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
177         settings->getNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
178         settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
179         settings->getNoiseParams("mgvalleys_np_rivers",             np_rivers);
180         settings->getNoiseParams("mgvalleys_np_massive_caves",      np_massive_caves);
181         settings->getNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
182         settings->getNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
183         settings->getNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
184 }
185
186
187 void MapgenValleysParams::writeParams(Settings *settings) const
188 {
189         settings->setFlagStr("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys, U32_MAX);
190         settings->setU16("mgvalleys_altitude_chill",     altitude_chill);
191         settings->setS16("mgvalleys_large_cave_depth",   large_cave_depth);
192         settings->setU16("mgvalleys_lava_features",      lava_features);
193         settings->setS16("mgvalleys_massive_cave_depth", massive_cave_depth);
194         settings->setU16("mgvalleys_river_depth",        river_depth);
195         settings->setU16("mgvalleys_river_size",         river_size);
196         settings->setU16("mgvalleys_water_features",     water_features);
197         settings->setFloat("mgvalleys_cave_width",       cave_width);
198
199         settings->setNoiseParams("mgvalleys_np_cave1",              np_cave1);
200         settings->setNoiseParams("mgvalleys_np_cave2",              np_cave2);
201         settings->setNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
202         settings->setNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
203         settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
204         settings->setNoiseParams("mgvalleys_np_rivers",             np_rivers);
205         settings->setNoiseParams("mgvalleys_np_massive_caves",      np_massive_caves);
206         settings->setNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
207         settings->setNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
208         settings->setNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
209 }
210
211
212 ///////////////////////////////////////
213
214
215 void MapgenValleys::makeChunk(BlockMakeData *data)
216 {
217         // Pre-conditions
218         assert(data->vmanip);
219         assert(data->nodedef);
220         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
221                 data->blockpos_requested.Y >= data->blockpos_min.Y &&
222                 data->blockpos_requested.Z >= data->blockpos_min.Z);
223         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
224                 data->blockpos_requested.Y <= data->blockpos_max.Y &&
225                 data->blockpos_requested.Z <= data->blockpos_max.Z);
226
227         this->generating = true;
228         this->vm = data->vmanip;
229         this->ndef = data->nodedef;
230
231         //TimeTaker t("makeChunk");
232
233         v3s16 blockpos_min = data->blockpos_min;
234         v3s16 blockpos_max = data->blockpos_max;
235         node_min = blockpos_min * MAP_BLOCKSIZE;
236         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
237         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
238         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
239
240         blockseed = getBlockSeed2(full_node_min, seed);
241
242         // Generate noise maps and base terrain height.
243         calculateNoise();
244
245         // Generate biome noises.  Note this must be executed strictly before
246         // generateTerrain, because generateTerrain depends on intermediate
247         // biome-related noises.
248         m_bgen->calcBiomeNoise(node_min);
249
250         // Generate base terrain with initial heightmaps
251         s16 stone_surface_max_y = generateTerrain();
252
253         // Build biomemap
254         m_bgen->getBiomes(heightmap);
255
256         // Place biome-specific nodes
257         MgStoneType stone_type = generateBiomes();
258
259         // Cave creation.
260         if (flags & MG_CAVES)
261                 generateCaves(stone_surface_max_y, large_cave_depth);
262
263         // Dungeon creation
264         if ((flags & MG_DUNGEONS) && node_max.Y < 50)
265                 generateDungeons(stone_surface_max_y, stone_type);
266
267         // Generate the registered decorations
268         if (flags & MG_DECORATIONS)
269                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
270
271         // Generate the registered ores
272         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
273
274         // Sprinkle some dust on top after everything else was generated
275         dustTopNodes();
276
277         //TimeTaker tll("liquid_lighting");
278
279         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
280
281         if (flags & MG_LIGHT)
282                 calcLighting(
283                                 node_min - v3s16(0, 1, 0),
284                                 node_max + v3s16(0, 1, 0),
285                                 full_node_min,
286                                 full_node_max);
287
288         //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
289         //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
290
291         this->generating = false;
292 }
293
294
295 // Populate the noise tables and do most of the
296 // calculation necessary to determine terrain height.
297 void MapgenValleys::calculateNoise()
298 {
299         //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
300
301         int x = node_min.X;
302         int y = node_min.Y - 1;
303         int z = node_min.Z;
304
305         //TimeTaker tcn("actualNoise");
306
307         noise_inter_valley_slope->perlinMap2D(x, z);
308         noise_rivers->perlinMap2D(x, z);
309         noise_terrain_height->perlinMap2D(x, z);
310         noise_valley_depth->perlinMap2D(x, z);
311         noise_valley_profile->perlinMap2D(x, z);
312
313         noise_inter_valley_fill->perlinMap3D(x, y, z);
314
315         //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
316
317         float heat_offset = 0.f;
318         float humidity_scale = 1.f;
319
320         // Altitude chill tends to reduce the average heat.
321         if (use_altitude_chill)
322                 heat_offset = 5.f;
323
324         // River humidity tends to increase the humidity range.
325         if (humid_rivers) {
326                 humidity_scale = 0.8f;
327         }
328
329         for (s32 index = 0; index < csize.X * csize.Z; index++) {
330                 m_bgen->heatmap[index] += heat_offset;
331                 m_bgen->humidmap[index] *= humidity_scale;
332         }
333
334         TerrainNoise tn;
335
336         u32 index = 0;
337         for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
338         for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
339                 // The parameters that we actually need to generate terrain
340                 //  are passed by address (and the return value).
341                 tn.terrain_height    = noise_terrain_height->result[index];
342                 // River noise is replaced with base terrain, which
343                 // is basically the height of the water table.
344                 tn.rivers            = &noise_rivers->result[index];
345                 // Valley depth noise is replaced with the valley
346                 // number that represents the height of terrain
347                 // over rivers and is used to determine about
348                 // how close a river is for humidity calculation.
349                 tn.valley            = &noise_valley_depth->result[index];
350                 tn.valley_profile    = noise_valley_profile->result[index];
351                 // Slope noise is replaced by the calculated slope
352                 // which is used to get terrain height in the slow
353                 // method, to create sharper mountains.
354                 tn.slope             = &noise_inter_valley_slope->result[index];
355                 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
356
357                 // This is the actual terrain height.
358                 float mount = terrainLevelFromNoise(&tn);
359                 noise_terrain_height->result[index] = mount;
360         }
361 }
362
363
364 // This keeps us from having to maintain two similar sets of
365 //  complicated code to determine ground level.
366 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
367 {
368         // The square function changes the behaviour of this noise:
369         //  very often small, and sometimes very high.
370         float valley_d = MYSQUARE(*tn->valley);
371
372         // valley_d is here because terrain is generally higher where valleys
373         //  are deep (mountains). base represents the height of the
374         //  rivers, most of the surface is above.
375         float base = tn->terrain_height + valley_d;
376
377         // "river" represents the distance from the river, in arbitrary units.
378         float river = fabs(*tn->rivers) - river_size_factor;
379
380         // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
381         //  Making "a" vary (0 < a <= 1) changes the shape of the valleys.
382         //  Try it with a geometry software !
383         //   (here x = "river" and a = valley_profile).
384         //  "valley" represents the height of the terrain, from the rivers.
385         {
386                 float t = river / tn->valley_profile;
387                 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
388         }
389
390         // approximate height of the terrain at this point
391         float mount = base + *tn->valley;
392
393         *tn->slope *= *tn->valley;
394
395         // Rivers are placed where "river" is negative, so where the original
396         //  noise value is close to zero.
397         // Base ground is returned as rivers since it's basically the water table.
398         *tn->rivers = base;
399         if (river < 0.f) {
400                 // Use the the function -sqrt(1-x^2) which models a circle.
401                 float depth;
402                 {
403                         float t = river / river_size_factor + 1;
404                         depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
405                 }
406
407                 // base - depth : height of the bottom of the river
408                 // water_level - 3 : don't make rivers below 3 nodes under the surface
409                 // We use three because that's as low as the swamp biomes go.
410                 // There is no logical equivalent to this using rangelim.
411                 mount = MYMIN(MYMAX(base - depth, (float)(water_level - 3)), mount);
412
413                 // Slope has no influence on rivers.
414                 *tn->slope = 0.f;
415         }
416
417         return mount;
418 }
419
420
421 // This avoids duplicating the code in terrainLevelFromNoise, adding
422 // only the final step of terrain generation without a noise map.
423 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
424 {
425         float mount = terrainLevelFromNoise(tn);
426         s16 y_start = myround(mount);
427
428         for (s16 y = y_start; y <= y_start + 1000; y++) {
429                 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
430
431                 if (fill * *tn->slope < y - mount) {
432                         mount = MYMAX(y - 1, mount);
433                         break;
434                 }
435         }
436
437         return mount;
438 }
439
440
441 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
442 {
443         // Check to make sure this isn't a request for a location in a river.
444         float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
445         if (fabs(rivers) < river_size_factor)
446                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
447
448         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
449         if (level_at_point <= water_level ||
450                         level_at_point > water_level + 32)
451                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
452         else
453                 return level_at_point;
454 }
455
456
457 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
458 {
459         TerrainNoise tn;
460
461         float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
462         float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
463         float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
464
465         tn.x                 = x;
466         tn.z                 = z;
467         tn.terrain_height    = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
468         tn.rivers            = &rivers;
469         tn.valley            = &valley;
470         tn.valley_profile    = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
471         tn.slope             = &inter_valley_slope;
472         tn.inter_valley_fill = 0.f;
473
474         return adjustedTerrainLevelFromNoise(&tn);
475 }
476
477
478 int MapgenValleys::generateTerrain()
479 {
480         // Raising this reduces the rate of evaporation.
481         static const float evaporation = 300.f;
482         // from the lua
483         static const float humidity_dropoff = 4.f;
484         // constant to convert altitude chill (compatible with lua) to heat
485         static const float alt_to_heat = 20.f;
486         // humidity reduction by altitude
487         static const float alt_to_humid = 10.f;
488
489         MapNode n_air(CONTENT_AIR);
490         MapNode n_river_water(c_river_water_source);
491         MapNode n_stone(c_stone);
492         MapNode n_water(c_water_source);
493
494         v3s16 em = vm->m_area.getExtent();
495         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
496         u32 index_2d = 0;
497
498         for (s16 z = node_min.Z; z <= node_max.Z; z++)
499         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
500                 float river_y = noise_rivers->result[index_2d];
501                 float surface_y = noise_terrain_height->result[index_2d];
502                 float slope = noise_inter_valley_slope->result[index_2d];
503                 float t_heat = m_bgen->heatmap[index_2d];
504
505                 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
506
507                 if (surface_y > surface_max_y)
508                         surface_max_y = ceil(surface_y);
509
510                 if (humid_rivers) {
511                         // Derive heat from (base) altitude. This will be most correct
512                         // at rivers, since other surface heights may vary below.
513                         if (use_altitude_chill && (surface_y > 0.f || river_y > 0.f))
514                                 t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill;
515
516                         // If humidity is low or heat is high, lower the water table.
517                         float delta = m_bgen->humidmap[index_2d] - 50.f;
518                         if (delta < 0.f) {
519                                 float t_evap = (t_heat - 32.f) / evaporation;
520                                 river_y += delta * MYMAX(t_evap, 0.08f);
521                         }
522                 }
523
524                 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
525                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
526
527                 // Mapgens concern themselves with stone and water.
528                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
529                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
530                                 float fill = noise_inter_valley_fill->result[index_3d];
531                                 float surface_delta = (float)y - surface_y;
532                                 bool river = y + 1 < river_y;
533
534                                 if (slope * fill > surface_delta) {
535                                         // ground
536                                         vm->m_data[index_data] = n_stone;
537                                         if (y > heightmap[index_2d])
538                                                 heightmap[index_2d] = y;
539                                         if (y > surface_max_y)
540                                                 surface_max_y = y;
541                                 } else if (y <= water_level) {
542                                         // sea
543                                         vm->m_data[index_data] = n_water;
544                                 } else if (river) {
545                                         // river
546                                         vm->m_data[index_data] = n_river_water;
547                                 } else {  // air
548                                         vm->m_data[index_data] = n_air;
549                                 }
550                         }
551
552                         vm->m_area.add_y(em, index_data, 1);
553                         index_3d += ystride;
554                 }
555
556                 // This happens if we're generating a chunk that doesn't
557                 // contain the terrain surface, in which case, we need
558                 // to set heightmap to a value outside of the chunk,
559                 // to avoid confusing lua mods that use heightmap.
560                 if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
561                         s16 surface_y_int = myround(surface_y);
562                         if (surface_y_int > node_max.Y + 1 || surface_y_int < node_min.Y - 1) {
563                                 // If surface_y is outside the chunk, it's good enough.
564                                 heightmap[index_2d] = surface_y_int;
565                         } else {
566                                 // If the ground is outside of this chunk, but surface_y
567                                 // is within the chunk, give a value outside.
568                                 heightmap[index_2d] = node_min.Y - 2;
569                         }
570                 }
571
572                 if (humid_rivers) {
573                         // Use base ground (water table) in a riverbed, to
574                         // avoid an unnatural rise in humidity.
575                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
576                         float humid = m_bgen->humidmap[index_2d];
577                         float water_depth = (t_alt - river_y) / humidity_dropoff;
578                         humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f));
579
580                         // Reduce humidity with altitude (ignoring riverbeds).
581                         // This is similar to the lua version's seawater adjustment,
582                         // but doesn't increase the base humidity, which causes
583                         // problems with the default biomes.
584                         if (t_alt > 0.f)
585                                 humid -= alt_to_humid * t_alt / altitude_chill;
586
587                         m_bgen->humidmap[index_2d] = humid;
588                 }
589
590                 // Assign the heat adjusted by any changed altitudes.
591                 // The altitude will change about half the time.
592                 if (use_altitude_chill) {
593                         // ground height ignoring riverbeds
594                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
595                         if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
596                                 // The altitude hasn't changed. Use the first result.
597                                 m_bgen->heatmap[index_2d] = t_heat;
598                         else if (t_alt > 0.f)
599                                 m_bgen->heatmap[index_2d] -= alt_to_heat * t_alt / altitude_chill;
600                 }
601         }
602
603         return surface_max_y;
604 }
605
606 void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
607 {
608         if (max_stone_y < node_min.Y)
609                 return;
610
611         noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
612         noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
613
614         PseudoRandom ps(blockseed + 72202);
615
616         MapNode n_air(CONTENT_AIR);
617         MapNode n_lava(c_lava_source);
618         MapNode n_water(c_river_water_source);
619
620         v3s16 em = vm->m_area.getExtent();
621
622         // Cave blend distance near YMIN, YMAX
623         const float massive_cave_blend = 128.f;
624         // noise threshold for massive caves
625         const float massive_cave_threshold = 0.6f;
626         // mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
627
628         float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
629         float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
630         bool made_a_big_one = false;
631
632         // Cache the tcave values as they only vary by altitude.
633         if (node_max.Y <= massive_cave_depth) {
634                 noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
635
636                 for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
637                         float tcave = massive_cave_threshold;
638
639                         if (y < yblmin) {
640                                 float t = (yblmin - y) / massive_cave_blend;
641                                 tcave += MYSQUARE(t);
642                         } else if (y > yblmax) {
643                                 float t = (y - yblmax) / massive_cave_blend;
644                                 tcave += MYSQUARE(t);
645                         }
646
647                         tcave_cache[y - node_min.Y + 1] = tcave;
648                 }
649         }
650
651         // lava_depth varies between one and ten as you approach
652         //  the bottom of the world.
653         s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
654         // This allows random lava spawns to be less common at the surface.
655         s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
656         // water_depth varies between ten and one on the way down.
657         s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
658         // This allows random water spawns to be more common at the surface.
659         s16 water_chance = MYCUBE(water_features_lim) * water_depth;
660
661         // Reduce the odds of overflows even further.
662         if (node_max.Y > water_level) {
663                 lava_chance /= 3;
664                 water_chance /= 3;
665         }
666
667         u32 index_2d = 0;
668         for (s16 z = node_min.Z; z <= node_max.Z; z++)
669         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
670                 Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index_2d]);
671                 bool tunnel_air_above = false;
672                 bool underground = false;
673                 u32 index_data = vm->m_area.index(x, node_max.Y, z);
674                 u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);
675
676                 // Dig caves on down loop to check for air above.
677                 // Don't excavate the overgenerated stone at node_max.Y + 1,
678                 // this creates a 'roof' over the tunnel, preventing light in
679                 // tunnels at mapchunk borders when generating mapchunks upwards.
680                 // This 'roof' is removed when the mapchunk above is generated.
681                 for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
682                                 index_3d -= ystride,
683                                 vm->m_area.add_y(em, index_data, -1)) {
684
685                         float terrain = noise_terrain_height->result[index_2d];
686
687                         // Saves some time.
688                         if (y > terrain + 10)
689                                 continue;
690                         else if (y < terrain - 40)
691                                 underground = true;
692
693                         // Dig massive caves.
694                         if (node_max.Y <= massive_cave_depth
695                                         && noise_massive_caves->result[index_3d]
696                                         > tcave_cache[y - node_min.Y + 1]) {
697                                 vm->m_data[index_data] = n_air;
698                                 made_a_big_one = true;
699                                 continue;
700                         }
701
702                         content_t c = vm->m_data[index_data].getContent();
703                         float d1 = contour(noise_cave1->result[index_3d]);
704                         float d2 = contour(noise_cave2->result[index_3d]);
705
706                         // River water is not set as ground content
707                         // in the default game. This can produce strange results
708                         // when a tunnel undercuts a river. However, that's not for
709                         // the mapgen to correct. Fix it in lua.
710
711                         if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
712                                 // in a tunnel
713                                 vm->m_data[index_data] = n_air;
714                                 tunnel_air_above = true;
715                         } else if (c == biome->c_filler || c == biome->c_stone) {
716                                 if (tunnel_air_above) {
717                                         // at the tunnel floor
718                                         s16 sr = ps.range(0, 39);
719                                         u32 j = index_data;
720                                         vm->m_area.add_y(em, j, 1);
721
722                                         if (sr > terrain - y) {
723                                                 // Put dirt in tunnels near the surface.
724                                                 if (underground)
725                                                         vm->m_data[index_data] = MapNode(biome->c_filler);
726                                                 else
727                                                         vm->m_data[index_data] = MapNode(biome->c_top);
728                                         } else if (sr < 3 && underground) {
729                                                 sr = abs(ps.next());
730                                                 if (lava_features_lim > 0 && y <= lava_max_height
731                                                                 && c == biome->c_stone && sr < lava_chance)
732                                                         vm->m_data[j] = n_lava;
733
734                                                 sr -= lava_chance;
735
736                                                 // If sr < 0 then we should have already placed lava --
737                                                 // don't immediately dump water on it.
738                                                 if (water_features_lim > 0 && y <= cave_water_max_height
739                                                                 && sr >= 0 && sr < water_chance)
740                                                         vm->m_data[j] = n_water;
741                                         }
742                                 }
743
744                                 tunnel_air_above = false;
745                                 underground = true;
746                         } else {
747                                 tunnel_air_above = false;
748                         }
749                 }
750         }
751
752         if (node_max.Y <= large_cave_depth && !made_a_big_one) {
753                 u32 bruises_count = ps.range(0, 2);
754                 for (u32 i = 0; i < bruises_count; i++) {
755                         CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
756                                 c_water_source, c_lava_source);
757
758                         cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);
759                 }
760         }
761 }