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