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