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