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