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