Mgvalleys: Don't let cavegen place biome nodes everywhere
[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         : Mapgen(mapgenid, params, emerge)
69 {
70         this->m_emerge = emerge;
71         this->bmgr = emerge->biomemgr;
72
73         //// amount of elements to skip for the next index
74         //// for noise/height/biome maps (not vmanip)
75         this->ystride = csize.X;
76         this->zstride = csize.X * (csize.Y + 2);
77         // 1-down overgeneration
78         this->zstride_1d = csize.X * (csize.Y + 1);
79
80         this->biomemap  = new u8[csize.X * csize.Z];
81         this->heightmap = new s16[csize.X * csize.Z];
82         this->heatmap   = NULL;
83         this->humidmap  = NULL;
84
85         this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
86                         g_settings->getU16("map_generation_limit"));
87
88         MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
89         this->spflags = sp->spflags;
90
91         this->humid_rivers       = (spflags & MGVALLEYS_HUMID_RIVERS);
92         this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
93
94         this->altitude_chill     = sp->altitude_chill;
95         this->humidity_adjust    = params->np_biome_humidity.offset - 50.f;
96         this->large_cave_depth   = sp->large_cave_depth;
97         this->lava_features_lim  = rangelim(sp->lava_features, 0, 10);
98         this->massive_cave_depth = sp->massive_cave_depth;
99         this->river_depth_bed    = sp->river_depth + 1.f;
100         this->river_size_factor  = sp->river_size / 100.f;
101         this->water_features_lim = rangelim(sp->water_features, 0, 10);
102
103         // a small chance of overflows if the settings are very high
104         this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
105         this->lava_max_height       = water_level + MYMAX(0, lava_features_lim - 4) * 50;
106
107         tcave_cache = new float[csize.Y + 2];
108
109         //// 2D Terrain noise
110         noise_filler_depth       = new Noise(&sp->np_filler_depth,       seed, csize.X, csize.Z);
111         noise_inter_valley_slope = new Noise(&sp->np_inter_valley_slope, seed, csize.X, csize.Z);
112         noise_rivers             = new Noise(&sp->np_rivers,             seed, csize.X, csize.Z);
113         noise_terrain_height     = new Noise(&sp->np_terrain_height,     seed, csize.X, csize.Z);
114         noise_valley_depth       = new Noise(&sp->np_valley_depth,       seed, csize.X, csize.Z);
115         noise_valley_profile     = new Noise(&sp->np_valley_profile,     seed, csize.X, csize.Z);
116
117         //// 3D Terrain noise
118         // 1-up 1-down overgeneration
119         noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
120         // 1-down overgeneraion
121         noise_cave1             = new Noise(&sp->np_cave1,             seed, csize.X, csize.Y + 1, csize.Z);
122         noise_cave2             = new Noise(&sp->np_cave2,             seed, csize.X, csize.Y + 1, csize.Z);
123         noise_massive_caves     = new Noise(&sp->np_massive_caves,     seed, csize.X, csize.Y + 1, csize.Z);
124
125         //// Biome noise
126         noise_heat_blend     = new Noise(&params->np_biome_heat_blend,     seed, csize.X, csize.Z);
127         noise_heat           = new Noise(&params->np_biome_heat,           seed, csize.X, csize.Z);
128         noise_humidity_blend = new Noise(&params->np_biome_humidity_blend, seed, csize.X, csize.Z);
129         noise_humidity       = new Noise(&params->np_biome_humidity,       seed, csize.X, csize.Z);
130
131         //// Resolve nodes to be used
132         INodeDefManager *ndef = emerge->ndef;
133
134         c_cobble               = ndef->getId("mapgen_cobble");
135         c_desert_stone         = ndef->getId("mapgen_desert_stone");
136         c_dirt                 = ndef->getId("mapgen_dirt");
137         c_lava_source          = ndef->getId("mapgen_lava_source");
138         c_mossycobble          = ndef->getId("mapgen_mossycobble");
139         c_river_water_source   = ndef->getId("mapgen_river_water_source");
140         c_sand                 = ndef->getId("mapgen_sand");
141         c_sandstonebrick       = ndef->getId("mapgen_sandstonebrick");
142         c_sandstone            = ndef->getId("mapgen_sandstone");
143         c_stair_cobble         = ndef->getId("mapgen_stair_cobble");
144         c_stair_sandstonebrick = ndef->getId("mapgen_stair_sandstonebrick");
145         c_stone                = ndef->getId("mapgen_stone");
146         c_water_source         = ndef->getId("mapgen_water_source");
147
148         if (c_mossycobble == CONTENT_IGNORE)
149                 c_mossycobble = c_cobble;
150         if (c_river_water_source == CONTENT_IGNORE)
151                 c_river_water_source = c_water_source;
152         if (c_sand == CONTENT_IGNORE)
153                 c_sand = c_stone;
154         if (c_sandstonebrick == CONTENT_IGNORE)
155                 c_sandstonebrick = c_sandstone;
156         if (c_stair_cobble == CONTENT_IGNORE)
157                 c_stair_cobble = c_cobble;
158         if (c_stair_sandstonebrick == CONTENT_IGNORE)
159                 c_stair_sandstonebrick = c_sandstone;
160 }
161
162
163 MapgenValleys::~MapgenValleys()
164 {
165         delete noise_cave1;
166         delete noise_cave2;
167         delete noise_filler_depth;
168         delete noise_heat;
169         delete noise_heat_blend;
170         delete noise_humidity;
171         delete noise_humidity_blend;
172         delete noise_inter_valley_fill;
173         delete noise_inter_valley_slope;
174         delete noise_rivers;
175         delete noise_massive_caves;
176         delete noise_terrain_height;
177         delete noise_valley_depth;
178         delete noise_valley_profile;
179
180         delete[] biomemap;
181         delete[] heightmap;
182         delete[] tcave_cache;
183 }
184
185
186 MapgenValleysParams::MapgenValleysParams()
187 {
188         spflags = MGVALLEYS_HUMID_RIVERS | MGVALLEYS_ALT_CHILL;
189
190         altitude_chill     = 90; // The altitude at which temperature drops by 20C.
191         large_cave_depth   = -33;
192         lava_features      = 0;  // How often water will occur in caves.
193         massive_cave_depth = -256;  // highest altitude of massive caves
194         river_depth        = 4;  // How deep to carve river channels.
195         river_size         = 5;  // How wide to make rivers.
196         water_features     = 0;  // How often water will occur in caves.
197
198         np_cave1              = NoiseParams(0,     12,   v3f(96,   96,   96),   52534, 4, 0.5,   2.0);
199         np_cave2              = NoiseParams(0,     12,   v3f(96,   96,   96),   10325, 4, 0.5,   2.0);
200         np_filler_depth       = NoiseParams(0.f,   1.2f, v3f(256,  256,  256),  1605,  3, 0.5f,  2.f);
201         np_inter_valley_fill  = NoiseParams(0.f,   1.f,  v3f(256,  512,  256),  1993,  6, 0.8f,  2.f);
202         np_inter_valley_slope = NoiseParams(0.5f,  0.5f, v3f(128,  128,  128),  746,   1, 1.f,   2.f);
203         np_rivers             = NoiseParams(0.f,   1.f,  v3f(256,  256,  256),  -6050, 5, 0.6f,  2.f);
204         np_massive_caves      = NoiseParams(0.f,   1.f,  v3f(768,  256,  768),  59033, 6, 0.63f, 2.f);
205         np_terrain_height     = NoiseParams(-10.f, 50.f, v3f(1024, 1024, 1024), 5202,  6, 0.4f,  2.f);
206         np_valley_depth       = NoiseParams(5.f,   4.f,  v3f(512,  512,  512),  -1914, 1, 1.f,   2.f);
207         np_valley_profile     = NoiseParams(0.6f,  0.5f, v3f(512,  512,  512),  777,   1, 1.f,   2.f);
208         }
209
210
211 void MapgenValleysParams::readParams(const Settings *settings)
212 {
213         settings->getFlagStrNoEx("mg_valleys_spflags", spflags, flagdesc_mapgen_valleys);
214
215         settings->getU16NoEx("mg_valleys_altitude_chill",     altitude_chill);
216         settings->getS16NoEx("mg_valleys_large_cave_depth",   large_cave_depth);
217         settings->getU16NoEx("mg_valleys_lava_features",      lava_features);
218         settings->getS16NoEx("mg_valleys_massive_cave_depth", massive_cave_depth);
219         settings->getU16NoEx("mg_valleys_river_depth",        river_depth);
220         settings->getU16NoEx("mg_valleys_river_size",         river_size);
221         settings->getU16NoEx("mg_valleys_water_features",     water_features);
222
223         settings->getNoiseParams("mg_valleys_np_cave1",              np_cave1);
224         settings->getNoiseParams("mg_valleys_np_cave2",              np_cave2);
225         settings->getNoiseParams("mg_valleys_np_filler_depth",       np_filler_depth);
226         settings->getNoiseParams("mg_valleys_np_inter_valley_fill",  np_inter_valley_fill);
227         settings->getNoiseParams("mg_valleys_np_inter_valley_slope", np_inter_valley_slope);
228         settings->getNoiseParams("mg_valleys_np_rivers",             np_rivers);
229         settings->getNoiseParams("mg_valleys_np_massive_caves",      np_massive_caves);
230         settings->getNoiseParams("mg_valleys_np_terrain_height",     np_terrain_height);
231         settings->getNoiseParams("mg_valleys_np_valley_depth",       np_valley_depth);
232         settings->getNoiseParams("mg_valleys_np_valley_profile",     np_valley_profile);
233 }
234
235
236 void MapgenValleysParams::writeParams(Settings *settings) const
237 {
238         settings->setFlagStr("mg_valleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX);
239
240         settings->setU16("mg_valleys_altitude_chill",     altitude_chill);
241         settings->setS16("mg_valleys_large_cave_depth",   large_cave_depth);
242         settings->setU16("mg_valleys_lava_features",      lava_features);
243         settings->setS16("mg_valleys_massive_cave_depth", massive_cave_depth);
244         settings->setU16("mg_valleys_river_depth",        river_depth);
245         settings->setU16("mg_valleys_river_size",         river_size);
246         settings->setU16("mg_valleys_water_features",     water_features);
247
248         settings->setNoiseParams("mg_valleys_np_cave1",              np_cave1);
249         settings->setNoiseParams("mg_valleys_np_cave2",              np_cave2);
250         settings->setNoiseParams("mg_valleys_np_filler_depth",       np_filler_depth);
251         settings->setNoiseParams("mg_valleys_np_inter_valley_fill",  np_inter_valley_fill);
252         settings->setNoiseParams("mg_valleys_np_inter_valley_slope", np_inter_valley_slope);
253         settings->setNoiseParams("mg_valleys_np_rivers",             np_rivers);
254         settings->setNoiseParams("mg_valleys_np_massive_caves",      np_massive_caves);
255         settings->setNoiseParams("mg_valleys_np_terrain_height",     np_terrain_height);
256         settings->setNoiseParams("mg_valleys_np_valley_depth",       np_valley_depth);
257         settings->setNoiseParams("mg_valleys_np_valley_profile",     np_valley_profile);
258 }
259
260
261 ///////////////////////////////////////
262
263
264 void MapgenValleys::makeChunk(BlockMakeData *data)
265 {
266         // Pre-conditions
267         assert(data->vmanip);
268         assert(data->nodedef);
269         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
270                 data->blockpos_requested.Y >= data->blockpos_min.Y &&
271                 data->blockpos_requested.Z >= data->blockpos_min.Z);
272         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
273                 data->blockpos_requested.Y <= data->blockpos_max.Y &&
274                 data->blockpos_requested.Z <= data->blockpos_max.Z);
275
276         this->generating = true;
277         this->vm = data->vmanip;
278         this->ndef = data->nodedef;
279
280         //TimeTaker t("makeChunk");
281
282         v3s16 blockpos_min = data->blockpos_min;
283         v3s16 blockpos_max = data->blockpos_max;
284         node_min = blockpos_min * MAP_BLOCKSIZE;
285         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
286         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
287         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
288
289         blockseed = getBlockSeed2(full_node_min, seed);
290
291         // Generate noise maps and base terrain height.
292         calculateNoise();
293
294         // Generate base terrain with initial heightmaps
295         s16 stone_surface_max_y = generateTerrain();
296
297         // Create biomemap at heightmap surface
298         bmgr->calcBiomes(csize.X, csize.Z, heatmap, humidmap, heightmap, biomemap);
299
300         // Actually place the biome-specific nodes
301         MgStoneType stone_type = generateBiomes(heatmap, humidmap);
302
303         // Cave creation.
304         if (flags & MG_CAVES)
305                 generateCaves(stone_surface_max_y);
306
307         // Dungeon creation
308         if ((flags & MG_DUNGEONS) && node_max.Y < 50 && (stone_surface_max_y >= node_min.Y)) {
309                 DungeonParams dp;
310
311                 dp.np_rarity  = nparams_dungeon_rarity;
312                 dp.np_density = nparams_dungeon_density;
313                 dp.np_wetness = nparams_dungeon_wetness;
314                 dp.c_water    = c_water_source;
315                 if (stone_type == STONE) {
316                         dp.c_cobble = c_cobble;
317                         dp.c_moss   = c_mossycobble;
318                         dp.c_stair  = c_stair_cobble;
319
320                         dp.diagonal_dirs = false;
321                         dp.mossratio     = 3.f;
322                         dp.holesize      = v3s16(1, 2, 1);
323                         dp.roomsize      = v3s16(0, 0, 0);
324                         dp.notifytype    = GENNOTIFY_DUNGEON;
325                 } else if (stone_type == DESERT_STONE) {
326                         dp.c_cobble = c_desert_stone;
327                         dp.c_moss   = c_desert_stone;
328                         dp.c_stair  = c_desert_stone;
329
330                         dp.diagonal_dirs = true;
331                         dp.mossratio     = 0.f;
332                         dp.holesize      = v3s16(2, 3, 2);
333                         dp.roomsize      = v3s16(2, 5, 2);
334                         dp.notifytype    = GENNOTIFY_TEMPLE;
335                 } else if (stone_type == SANDSTONE) {
336                         dp.c_cobble = c_sandstonebrick;
337                         dp.c_moss   = c_sandstonebrick;
338                         dp.c_stair  = c_sandstonebrick;
339
340                         dp.diagonal_dirs = false;
341                         dp.mossratio     = 0.f;
342                         dp.holesize      = v3s16(2, 2, 2);
343                         dp.roomsize      = v3s16(2, 0, 2);
344                         dp.notifytype    = GENNOTIFY_DUNGEON;
345                 }
346
347                 DungeonGen dgen(this, &dp);
348                 dgen.generate(blockseed, full_node_min, full_node_max);
349         }
350
351         // Generate the registered decorations
352         if (flags & MG_DECORATIONS)
353                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
354
355         // Generate the registered ores
356         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
357
358         // Sprinkle some dust on top after everything else was generated
359         dustTopNodes();
360
361         //TimeTaker tll("liquid_lighting");
362
363         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
364
365         if (flags & MG_LIGHT)
366                 calcLighting(
367                                 node_min - v3s16(0, 1, 0),
368                                 node_max + v3s16(0, 1, 0),
369                                 full_node_min,
370                                 full_node_max);
371
372         //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
373         //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
374
375         this->generating = false;
376 }
377
378
379 // Populate the noise tables and do most of the
380 // calculation necessary to determine terrain height.
381 void MapgenValleys::calculateNoise()
382 {
383         //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
384
385         int x = node_min.X;
386         int y = node_min.Y - 1;
387         int z = node_min.Z;
388
389         //TimeTaker tcn("actualNoise");
390
391         noise_filler_depth->perlinMap2D(x, z);
392         noise_heat_blend->perlinMap2D(x, z);
393         noise_heat->perlinMap2D(x, z);
394         noise_humidity_blend->perlinMap2D(x, z);
395         noise_humidity->perlinMap2D(x, z);
396         noise_inter_valley_slope->perlinMap2D(x, z);
397         noise_rivers->perlinMap2D(x, z);
398         noise_terrain_height->perlinMap2D(x, z);
399         noise_valley_depth->perlinMap2D(x, z);
400         noise_valley_profile->perlinMap2D(x, z);
401
402         noise_inter_valley_fill->perlinMap3D(x, y, z);
403
404         //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
405
406         float heat_offset = 0.f;
407         float humidity_scale = 1.f;
408
409         // Altitude chill tends to reduce the average heat.
410         if (use_altitude_chill)
411                 heat_offset = 5.f;
412
413         // River humidity tends to increase the humidity range.
414         if (humid_rivers) {
415                 humidity_scale = 0.8f;
416         }
417
418         for (s32 index = 0; index < csize.X * csize.Z; index++) {
419                 noise_heat->result[index] += noise_heat_blend->result[index] + heat_offset;
420                 noise_humidity->result[index] *= humidity_scale;
421                 noise_humidity->result[index] += noise_humidity_blend->result[index];
422         }
423
424         TerrainNoise tn;
425
426         u32 index = 0;
427         for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
428         for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
429                 // The parameters that we actually need to generate terrain
430                 //  are passed by address (and the return value).
431                 tn.terrain_height    = noise_terrain_height->result[index];
432                 // River noise is replaced with base terrain, which
433                 // is basically the height of the water table.
434                 tn.rivers            = &noise_rivers->result[index];
435                 // Valley depth noise is replaced with the valley
436                 // number that represents the height of terrain
437                 // over rivers and is used to determine about
438                 // how close a river is for humidity calculation.
439                 tn.valley            = &noise_valley_depth->result[index];
440                 tn.valley_profile    = noise_valley_profile->result[index];
441                 // Slope noise is replaced by the calculated slope
442                 // which is used to get terrain height in the slow
443                 // method, to create sharper mountains.
444                 tn.slope             = &noise_inter_valley_slope->result[index];
445                 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
446
447                 // This is the actual terrain height.
448                 float mount = terrainLevelFromNoise(&tn);
449                 noise_terrain_height->result[index] = mount;
450         }
451
452         heatmap  = noise_heat->result;
453         humidmap = noise_humidity->result;
454 }
455
456
457 // This keeps us from having to maintain two similar sets of
458 //  complicated code to determine ground level.
459 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
460 {
461         // The square function changes the behaviour of this noise:
462         //  very often small, and sometimes very high.
463         float valley_d = MYSQUARE(*tn->valley);
464
465         // valley_d is here because terrain is generally higher where valleys
466         //  are deep (mountains). base represents the height of the
467         //  rivers, most of the surface is above.
468         float base = tn->terrain_height + valley_d;
469
470         // "river" represents the distance from the river, in arbitrary units.
471         float river = fabs(*tn->rivers) - river_size_factor;
472
473         // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
474         //  Making "a" vary (0 < a <= 1) changes the shape of the valleys.
475         //  Try it with a geometry software !
476         //   (here x = "river" and a = valley_profile).
477         //  "valley" represents the height of the terrain, from the rivers.
478         {
479                 float t = river / tn->valley_profile;
480                 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
481         }
482
483         // approximate height of the terrain at this point
484         float mount = base + *tn->valley;
485
486         *tn->slope *= *tn->valley;
487
488         // Rivers are placed where "river" is negative, so where the original
489         //  noise value is close to zero.
490         // Base ground is returned as rivers since it's basically the water table.
491         *tn->rivers = base;
492         if (river < 0.f) {
493                 // Use the the function -sqrt(1-x^2) which models a circle.
494                 float depth;
495                 {
496                         float t = river / river_size_factor + 1;
497                         depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
498                 }
499
500                 // base - depth : height of the bottom of the river
501                 // water_level - 3 : don't make rivers below 3 nodes under the surface
502                 // We use three because that's as low as the swamp biomes go.
503                 // There is no logical equivalent to this using rangelim.
504                 mount = MYMIN(MYMAX(base - depth, (float)(water_level - 3)), mount);
505
506                 // Slope has no influence on rivers.
507                 *tn->slope = 0.f;
508         }
509
510         return mount;
511 }
512
513
514 // This avoids duplicating the code in terrainLevelFromNoise, adding
515 // only the final step of terrain generation without a noise map.
516 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
517 {
518         float mount = terrainLevelFromNoise(tn);
519         s16 y_start = myround(mount);
520
521         for (s16 y = y_start; y <= y_start + 1000; y++) {
522                 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
523
524                 if (fill * *tn->slope < y - mount) {
525                         mount = MYMAX(y - 1, mount);
526                         break;
527                 }
528         }
529
530         return mount;
531 }
532
533
534 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
535 {
536         // Check to make sure this isn't a request for a location in a river.
537         float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
538         if (fabs(rivers) < river_size_factor)
539                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
540
541         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
542         if (level_at_point <= water_level ||
543                         level_at_point > water_level + 32)
544                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
545         else
546                 return level_at_point;
547 }
548
549
550 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
551 {
552         TerrainNoise tn;
553
554         float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
555         float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
556         float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
557
558         tn.x                 = x;
559         tn.z                 = z;
560         tn.terrain_height    = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
561         tn.rivers            = &rivers;
562         tn.valley            = &valley;
563         tn.valley_profile    = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
564         tn.slope             = &inter_valley_slope;
565         tn.inter_valley_fill = 0.f;
566
567         return adjustedTerrainLevelFromNoise(&tn);
568 }
569
570
571 int MapgenValleys::generateTerrain()
572 {
573         // Raising this reduces the rate of evaporation.
574         static const float evaporation = 300.f;
575         // from the lua
576         static const float humidity_dropoff = 4.f;
577         // constant to convert altitude chill (compatible with lua) to heat
578         static const float alt_to_heat = 20.f;
579         // humidity reduction by altitude
580         static const float alt_to_humid = 10.f;
581
582         MapNode n_air(CONTENT_AIR);
583         MapNode n_river_water(c_river_water_source);
584         MapNode n_sand(c_sand);
585         MapNode n_stone(c_stone);
586         MapNode n_water(c_water_source);
587
588         v3s16 em = vm->m_area.getExtent();
589         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
590         u32 index_2d = 0;
591
592         for (s16 z = node_min.Z; z <= node_max.Z; z++)
593         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
594                 float river_y = noise_rivers->result[index_2d];
595                 float surface_y = noise_terrain_height->result[index_2d];
596                 float slope = noise_inter_valley_slope->result[index_2d];
597                 float t_heat = noise_heat->result[index_2d];
598
599                 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
600
601                 if (surface_y > surface_max_y)
602                         surface_max_y = ceil(surface_y);
603
604                 if (humid_rivers) {
605                         // Derive heat from (base) altitude. This will be most correct
606                         // at rivers, since other surface heights may vary below.
607                         if (use_altitude_chill && (surface_y > 0.f || river_y > 0.f))
608                                 t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill;
609
610                         // If humidity is low or heat is high, lower the water table.
611                         float delta = noise_humidity->result[index_2d] - 50.f;
612                         if (delta < 0.f) {
613                                 float t_evap = (t_heat - 32.f) / evaporation;
614                                 river_y += delta * MYMAX(t_evap, 0.08f);
615                         }
616                 }
617
618                 u32 index_3d = (z - node_min.Z) * zstride + (x - node_min.X);
619                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
620
621                 // Mapgens concern themselves with stone and water.
622                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
623                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
624                                 float fill = noise_inter_valley_fill->result[index_3d];
625                                 float surface_delta = (float)y - surface_y;
626                                 bool river = y + 1 < river_y;
627
628                                 if (fabs(surface_delta) <= 0.5f && y > water_level && river) {
629                                         // river bottom
630                                         vm->m_data[index_data] = n_sand;
631                                 } else if (slope * fill > surface_delta) {
632                                         // ground
633                                         vm->m_data[index_data] = n_stone;
634                                         if (y > heightmap[index_2d])
635                                                 heightmap[index_2d] = y;
636                                         if (y > surface_max_y)
637                                                 surface_max_y = y;
638                                 } else if (y <= water_level) {
639                                         // sea
640                                         vm->m_data[index_data] = n_water;
641                                 } else if (river) {
642                                         // river
643                                         vm->m_data[index_data] = n_river_water;
644                                 } else {
645                                         vm->m_data[index_data] = n_air;
646                                 }
647                         }
648
649                         vm->m_area.add_y(em, index_data, 1);
650                         index_3d += ystride;
651                 }
652
653                 // This happens if we're generating a chunk that doesn't
654                 // contain the terrain surface, in which case, we need
655                 // to set heightmap to a value outside of the chunk,
656                 // to avoid confusing lua mods that use heightmap.
657                 if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
658                         s16 surface_y_int = myround(surface_y);
659                         if (surface_y_int > node_max.Y + 1 || surface_y_int < node_min.Y - 1) {
660                                 // If surface_y is outside the chunk, it's good enough.
661                                 heightmap[index_2d] = surface_y_int;
662                         } else {
663                                 // If the ground is outside of this chunk, but surface_y
664                                 // is within the chunk, give a value outside.
665                                 heightmap[index_2d] = node_min.Y - 2;
666                         }
667                 }
668
669                 if (humid_rivers) {
670                         // Use base ground (water table) in a riverbed, to
671                         // avoid an unnatural rise in humidity.
672                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
673                         float humid = noise_humidity->result[index_2d];
674                         float water_depth = (t_alt - river_y) / humidity_dropoff;
675                         humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f));
676
677                         // Reduce humidity with altitude (ignoring riverbeds).
678                         // This is similar to the lua version's seawater adjustment,
679                         // but doesn't increase the base humidity, which causes
680                         // problems with the default biomes.
681                         if (t_alt > 0.f)
682                                 humid -= alt_to_humid * t_alt / altitude_chill;
683
684                         noise_humidity->result[index_2d] = humid;
685                 }
686
687                 // Assign the heat adjusted by any changed altitudes.
688                 // The altitude will change about half the time.
689                 if (use_altitude_chill) {
690                         // ground height ignoring riverbeds
691                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
692                         if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
693                                 // The altitude hasn't changed. Use the first result.
694                                 noise_heat->result[index_2d] = t_heat;
695                         else if (t_alt > 0.f)
696                                 noise_heat->result[index_2d] -= alt_to_heat * t_alt / altitude_chill;
697                 }
698         }
699
700         return surface_max_y;
701 }
702
703
704 MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map)
705 {
706         v3s16 em = vm->m_area.getExtent();
707         u32 index = 0;
708         MgStoneType stone_type = STONE;
709
710         for (s16 z = node_min.Z; z <= node_max.Z; z++)
711         for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
712                 Biome *biome = NULL;
713                 u16 depth_top = 0;
714                 u16 base_filler = 0;
715                 u16 depth_water_top = 0;
716                 u32 vi = vm->m_area.index(x, node_max.Y, z);
717
718                 // Check node at base of mapchunk above, either a node of a previously
719                 // generated mapchunk or if not, a node of overgenerated base terrain.
720                 content_t c_above = vm->m_data[vi + em.X].getContent();
721                 bool air_above = c_above == CONTENT_AIR;
722                 bool water_above = (c_above == c_water_source || c_above == c_river_water_source);
723
724                 // If there is air or water above enable top/filler placement, otherwise force
725                 // nplaced to stone level by setting a number exceeding any possible filler depth.
726                 u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
727
728                 for (s16 y = node_max.Y; y >= node_min.Y; y--) {
729                         content_t c = vm->m_data[vi].getContent();
730
731                         // Biome is recalculated each time an upper surface is detected while
732                         // working down a column. The selected biome then remains in effect for
733                         // all nodes below until the next surface and biome recalculation.
734                         // Biome is recalculated:
735                         // 1. At the surface of stone below air or water.
736                         // 2. At the surface of water below air.
737                         // 3. When stone or water is detected but biome has not yet been calculated.
738                         if ((c == c_stone && (air_above || water_above || !biome))
739                                         || ((c == c_water_source || c == c_river_water_source)
740                                                         && (air_above || !biome))) {
741                                 // Both heat and humidity have already been adjusted for altitude.
742                                 biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
743
744                                 depth_top = biome->depth_top;
745                                 base_filler = MYMAX(depth_top
746                                                 + biome->depth_filler
747                                                 + noise_filler_depth->result[index], 0.f);
748                                 depth_water_top = biome->depth_water_top;
749
750                                 // Detect stone type for dungeons during every biome calculation.
751                                 // This is more efficient than detecting per-node and will not
752                                 // miss any desert stone or sandstone biomes.
753                                 if (biome->c_stone == c_desert_stone)
754                                         stone_type = DESERT_STONE;
755                                 else if (biome->c_stone == c_sandstone)
756                                         stone_type = SANDSTONE;
757                         }
758
759                         if (c == c_stone) {
760                                 content_t c_below = vm->m_data[vi - em.X].getContent();
761
762                                 // If the node below isn't solid, make this node stone, so that
763                                 // any top/filler nodes above are structurally supported.
764                                 // This is done by aborting the cycle of top/filler placement
765                                 // immediately by forcing nplaced to stone level.
766                                 if (c_below == CONTENT_AIR
767                                                 || c_below == c_water_source
768                                                 || c_below == c_river_water_source)
769                                         nplaced = U16_MAX;
770
771                                 if (nplaced < depth_top) {
772                                         vm->m_data[vi] = MapNode(biome->c_top);
773                                         nplaced++;
774                                 } else if (nplaced < base_filler) {
775                                         vm->m_data[vi] = MapNode(biome->c_filler);
776                                         nplaced++;
777                                 } else {
778                                         vm->m_data[vi] = MapNode(biome->c_stone);
779                                 }
780
781                                 air_above = false;
782                                 water_above = false;
783                         } else if (c == c_water_source) {
784                                 vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
785                                                 ? biome->c_water_top : biome->c_water);
786                                 nplaced = 0;  // Enable top/filler placement for next surface
787                                 air_above = false;
788                                 water_above = true;
789                         } else if (c == c_river_water_source) {
790                                 vm->m_data[vi] = MapNode(biome->c_river_water);
791                                 nplaced = depth_top;  // Enable filler placement for next surface
792                                 air_above = false;
793                                 water_above = true;
794                         } else if (c == CONTENT_AIR) {
795                                 nplaced = 0;  // Enable top/filler placement for next surface
796                                 air_above = true;
797                                 water_above = false;
798                         } else {  // Possible various nodes overgenerated from neighbouring mapchunks
799                                 nplaced = U16_MAX;  // Disable top/filler placement
800                                 air_above = false;
801                                 water_above = false;
802                         }
803
804                         vm->m_area.add_y(em, vi, -1);
805                 }
806         }
807
808         return stone_type;
809 }
810
811
812 void MapgenValleys::dustTopNodes()
813 {
814         if (node_max.Y < water_level)
815                 return;
816
817         v3s16 em = vm->m_area.getExtent();
818         u32 index = 0;
819
820         for (s16 z = node_min.Z; z <= node_max.Z; z++)
821         for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
822                 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
823
824                 if (biome->c_dust == CONTENT_IGNORE)
825                         continue;
826
827                 u32 vi = vm->m_area.index(x, full_node_max.Y, z);
828                 content_t c_full_max = vm->m_data[vi].getContent();
829                 s16 y_start;
830
831                 if (c_full_max == CONTENT_AIR) {
832                         y_start = full_node_max.Y - 1;
833                 } else if (c_full_max == CONTENT_IGNORE) {
834                         vi = vm->m_area.index(x, node_max.Y + 1, z);
835                         content_t c_max = vm->m_data[vi].getContent();
836
837                         if (c_max == CONTENT_AIR)
838                                 y_start = node_max.Y;
839                         else
840                                 continue;
841                 } else {
842                         continue;
843                 }
844
845                 vi = vm->m_area.index(x, y_start, z);
846                 for (s16 y = y_start; y >= node_min.Y - 1; y--) {
847                         if (vm->m_data[vi].getContent() != CONTENT_AIR)
848                                 break;
849
850                         vm->m_area.add_y(em, vi, -1);
851                 }
852
853                 content_t c = vm->m_data[vi].getContent();
854                 if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
855                         vm->m_area.add_y(em, vi, 1);
856                         vm->m_data[vi] = MapNode(biome->c_dust);
857                 }
858         }
859 }
860
861
862 void MapgenValleys::generateCaves(s16 max_stone_y)
863 {
864         if (max_stone_y < node_min.Y)
865                 return;
866
867         noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
868         noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
869
870         PseudoRandom ps(blockseed + 72202);
871
872         MapNode n_air(CONTENT_AIR);
873         MapNode n_lava(c_lava_source);
874         MapNode n_water(c_river_water_source);
875
876         v3s16 em = vm->m_area.getExtent();
877
878         // Cave blend distance near YMIN, YMAX
879         const float massive_cave_blend = 128.f;
880         // noise threshold for massive caves
881         const float massive_cave_threshold = 0.6f;
882         // mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
883
884         float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
885         float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
886         bool made_a_big_one = false;
887
888         // Cache the tcave values as they only vary by altitude.
889         if (node_max.Y <= massive_cave_depth) {
890                 noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
891
892                 for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
893                         float tcave = massive_cave_threshold;
894
895                         if (y < yblmin) {
896                                 float t = (yblmin - y) / massive_cave_blend;
897                                 tcave += MYSQUARE(t);
898                         } else if (y > yblmax) {
899                                 float t = (y - yblmax) / massive_cave_blend;
900                                 tcave += MYSQUARE(t);
901                         }
902
903                         tcave_cache[y - node_min.Y + 1] = tcave;
904                 }
905         }
906
907         // lava_depth varies between one and ten as you approach
908         //  the bottom of the world.
909         s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
910         // This allows random lava spawns to be less common at the surface.
911         s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
912         // water_depth varies between ten and one on the way down.
913         s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
914         // This allows random water spawns to be more common at the surface.
915         s16 water_chance = MYCUBE(water_features_lim) * water_depth;
916
917         // Reduce the odds of overflows even further.
918         if (node_max.Y > water_level) {
919                 lava_chance /= 3;
920                 water_chance /= 3;
921         }
922
923         u32 index_2d = 0;
924         for (s16 z = node_min.Z; z <= node_max.Z; z++)
925         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
926                 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
927                 bool tunnel_air_above = false;
928                 bool underground = false;
929                 u32 index_data = vm->m_area.index(x, node_max.Y, z);
930                 u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);
931
932                 // Dig caves on down loop to check for air above.
933                 // Don't excavate the overgenerated stone at node_max.Y + 1,
934                 // this creates a 'roof' over the tunnel, preventing light in
935                 // tunnels at mapchunk borders when generating mapchunks upwards.
936                 // This 'roof' is removed when the mapchunk above is generated.
937                 for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
938                                 index_3d -= ystride,
939                                 vm->m_area.add_y(em, index_data, -1)) {
940
941                         float terrain = noise_terrain_height->result[index_2d];
942
943                         // Saves some time.
944                         if (y > terrain + 10)
945                                 continue;
946                         else if (y < terrain - 40)
947                                 underground = true;
948
949                         // Dig massive caves.
950                         if (node_max.Y <= massive_cave_depth
951                                         && noise_massive_caves->result[index_3d]
952                                         > tcave_cache[y - node_min.Y + 1]) {
953                                 vm->m_data[index_data] = n_air;
954                                 made_a_big_one = true;
955                                 continue;
956                         }
957
958                         content_t c = vm->m_data[index_data].getContent();
959                         float d1 = contour(noise_cave1->result[index_3d]);
960                         float d2 = contour(noise_cave2->result[index_3d]);
961
962                         // River water is not set as ground content
963                         // in the default game. This can produce strange results
964                         // when a tunnel undercuts a river. However, that's not for
965                         // the mapgen to correct. Fix it in lua.
966
967                         if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
968                                 // in a tunnel
969                                 vm->m_data[index_data] = n_air;
970                                 tunnel_air_above = true;
971                         } else if (c == biome->c_filler || c == biome->c_stone) {
972                                 if (tunnel_air_above) {
973                                         // at the tunnel floor
974                                         s16 sr = ps.range(0, 39);
975                                         u32 j = index_data;
976                                         vm->m_area.add_y(em, j, 1);
977
978                                         if (sr > terrain - y) {
979                                                 // Put dirt in tunnels near the surface.
980                                                 if (underground)
981                                                         vm->m_data[index_data] = MapNode(biome->c_filler);
982                                                 else
983                                                         vm->m_data[index_data] = MapNode(biome->c_top);
984                                         } else if (sr < 3 && underground) {
985                                                 sr = abs(ps.next());
986                                                 if (lava_features_lim > 0 && y <= lava_max_height
987                                                                 && c == biome->c_stone && sr < lava_chance)
988                                                         vm->m_data[j] = n_lava;
989
990                                                 sr -= lava_chance;
991
992                                                 // If sr < 0 then we should have already placed lava --
993                                                 // don't immediately dump water on it.
994                                                 if (water_features_lim > 0 && y <= cave_water_max_height
995                                                                 && sr >= 0 && sr < water_chance)
996                                                         vm->m_data[j] = n_water;
997                                         }
998                                 }
999
1000                                 tunnel_air_above = false;
1001                                 underground = true;
1002                         } else {
1003                                 tunnel_air_above = false;
1004                         }
1005                 }
1006         }
1007
1008         if (node_max.Y <= large_cave_depth && !made_a_big_one) {
1009                 u32 bruises_count = ps.range(0, 2);
1010                 for (u32 i = 0; i < bruises_count; i++) {
1011                         CaveV5 cave(this, &ps);
1012                         cave.makeCave(node_min, node_max, max_stone_y);
1013                 }
1014         }
1015 }