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