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