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