]> git.lizzy.rs Git - minetest.git/blob - src/mapgen_valleys.cpp
FindSpawnPos: Let mapgens decide what spawn altitude is suitable
[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         for (s32 index = 0; index < csize.X * csize.Z; index++) {
403                 noise_heat->result[index] += noise_heat_blend->result[index];
404                 noise_humidity->result[index] += noise_humidity_blend->result[index];
405         }
406
407         TerrainNoise tn;
408
409         u32 index = 0;
410         for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
411         for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
412                 // The parameters that we actually need to generate terrain
413                 //  are passed by address (and the return value).
414                 tn.terrain_height    = noise_terrain_height->result[index];
415                 // River noise is replaced with base terrain, which
416                 // is basically the height of the water table.
417                 tn.rivers            = &noise_rivers->result[index];
418                 // Valley depth noise is replaced with the valley
419                 // number that represents the height of terrain
420                 // over rivers and is used to determine about
421                 // how close a river is for humidity calculation.
422                 tn.valley            = &noise_valley_depth->result[index];
423                 tn.valley_profile    = noise_valley_profile->result[index];
424                 // Slope noise is replaced by the calculated slope
425                 // which is used to get terrain height in the slow
426                 // method, to create sharper mountains.
427                 tn.slope             = &noise_inter_valley_slope->result[index];
428                 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
429
430                 // This is the actual terrain height.
431                 float mount = terrainLevelFromNoise(&tn);
432                 noise_terrain_height->result[index] = mount;
433         }
434
435         heatmap  = noise_heat->result;
436         humidmap = noise_humidity->result;
437 }
438
439
440 // This keeps us from having to maintain two similar sets of
441 //  complicated code to determine ground level.
442 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
443 {
444         // The square function changes the behaviour of this noise:
445         //  very often small, and sometimes very high.
446         float valley_d = MYSQUARE(*tn->valley);
447
448         // valley_d is here because terrain is generally higher where valleys
449         //  are deep (mountains). base represents the height of the
450         //  rivers, most of the surface is above.
451         float base = tn->terrain_height + valley_d;
452
453         // "river" represents the distance from the river, in arbitrary units.
454         float river = fabs(*tn->rivers) - river_size_factor;
455
456         // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
457         //  Making "a" vary (0 < a <= 1) changes the shape of the valleys.
458         //  Try it with a geometry software !
459         //   (here x = "river" and a = valley_profile).
460         //  "valley" represents the height of the terrain, from the rivers.
461         {
462                 float t = river / tn->valley_profile;
463                 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
464         }
465
466         // approximate height of the terrain at this point
467         float mount = base + *tn->valley;
468
469         *tn->slope *= *tn->valley;
470
471         // Rivers are placed where "river" is negative, so where the original
472         //  noise value is close to zero.
473         // Base ground is returned as rivers since it's basically the water table.
474         *tn->rivers = base;
475         if (river < 0.f) {
476                 // Use the the function -sqrt(1-x^2) which models a circle.
477                 float depth;
478                 {
479                         float t = river / river_size_factor + 1;
480                         depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
481                 }
482
483                 // base - depth : height of the bottom of the river
484                 // water_level - 6 : don't make rivers below 6 nodes under the surface
485                 // There is no logical equivalent to this using rangelim.
486                 mount = MYMIN(MYMAX(base - depth, (float) (water_level - 6)), mount);
487
488                 // Slope has no influence on rivers.
489                 *tn->slope = 0.f;
490         }
491
492         return mount;
493 }
494
495
496 // This avoids duplicating the code in terrainLevelFromNoise, adding
497 // only the final step of terrain generation without a noise map.
498 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
499 {
500         float mount = terrainLevelFromNoise(tn);
501         s16 y_start = myround(mount);
502
503         for (s16 y = y_start; y <= y_start + 1000; y++) {
504                 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
505
506                 if (fill * *tn->slope <= y - mount) {
507                         mount = MYMAX(y - 1, mount);
508                         break;
509                 }
510         }
511
512         return mount;
513 }
514
515
516 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
517 {
518         // Check to make sure this isn't a request for a location in a river.
519         float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
520         if (fabs(rivers) < river_size_factor)
521                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
522
523         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
524         if (level_at_point <= water_level ||
525                         level_at_point > water_level + 16)
526                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
527         else
528                 return level_at_point;
529 }
530
531
532 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
533 {
534         TerrainNoise tn;
535
536         float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
537         float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
538         float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
539
540         tn.x                 = x;
541         tn.z                 = z;
542         tn.terrain_height    = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
543         tn.rivers            = &rivers;
544         tn.valley            = &valley;
545         tn.valley_profile    = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
546         tn.slope             = &inter_valley_slope;
547         tn.inter_valley_fill = 0.f;
548
549         return adjustedTerrainLevelFromNoise(&tn);
550 }
551
552
553 int MapgenValleys::generateTerrain()
554 {
555         MapNode n_air(CONTENT_AIR);
556         MapNode n_river_water(c_river_water_source);
557         MapNode n_sand(c_sand);
558         MapNode n_stone(c_stone);
559         MapNode n_water(c_water_source);
560
561         v3s16 em = vm->m_area.getExtent();
562         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
563         u32 index_2d = 0;
564
565         for (s16 z = node_min.Z; z <= node_max.Z; z++)
566         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
567                 s16 river_y = floor(noise_rivers->result[index_2d]);
568                 s16 surface_y = floor(noise_terrain_height->result[index_2d]);
569                 float slope = noise_inter_valley_slope->result[index_2d];
570
571                 heightmap[index_2d] = surface_y;
572
573                 if (surface_y > surface_max_y)
574                         surface_max_y = surface_y;
575
576                 u32 index_3d = (z - node_min.Z) * zstride + (x - node_min.X);
577                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
578
579                 // Mapgens concern themselves with stone and water.
580                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
581                         float fill = 0.f;
582                         fill = noise_inter_valley_fill->result[index_3d];
583
584                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
585                                 bool river = (river_y > surface_y);
586
587                                 if (river && y == surface_y) {
588                                         // river bottom
589                                         vm->m_data[index_data] = n_sand;
590                                 } else if (river && y <= surface_y) {
591                                         // ground
592                                         vm->m_data[index_data] = n_stone;
593                                 } else if (river && y < river_y) {
594                                         // river
595                                         vm->m_data[index_data] = n_river_water;
596                                 } else if ((!river) && myround(fill * slope) >= y - surface_y) {
597                                         // ground
598                                         vm->m_data[index_data] = n_stone;
599                                         heightmap[index_2d] = surface_max_y = y;
600                                 } else if (y <= water_level) {
601                                         // sea
602                                         vm->m_data[index_data] = n_water;
603                                 } else {
604                                         vm->m_data[index_data] = n_air;
605                                 }
606                         }
607
608                         vm->m_area.add_y(em, index_data, 1);
609                         index_3d += ystride;
610                 }
611
612                 // Although the original valleys adjusts humidity by distance
613                 // from seawater, this causes problems with the default biomes.
614                 // Adjust only by freshwater proximity.
615                 const float humidity_offset = 0.8f;  // derived by testing
616                 if (humid_rivers)
617                         noise_humidity->result[index_2d] *= (1 + pow(0.5f, MYMAX((surface_max_y
618                                         - noise_rivers->result[index_2d]) / 3.f, 0.f))) * humidity_offset;
619
620                 // Assign the heat adjusted by altitude.
621                 if (use_altitude_chill && surface_max_y > 0)
622                         noise_heat->result[index_2d] *=
623                                 pow(0.5f, (surface_max_y - altitude_chill / 3.f) / altitude_chill);
624         }
625
626         return surface_max_y;
627 }
628
629
630 MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map)
631 {
632         v3s16 em = vm->m_area.getExtent();
633         u32 index = 0;
634         MgStoneType stone_type = STONE;
635
636         for (s16 z = node_min.Z; z <= node_max.Z; z++)
637         for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
638                 Biome *biome = NULL;
639                 u16 depth_top = 0;
640                 u16 base_filler = 0;
641                 u16 depth_water_top = 0;
642                 u32 vi = vm->m_area.index(x, node_max.Y, z);
643
644                 // Check node at base of mapchunk above, either a node of a previously
645                 // generated mapchunk or if not, a node of overgenerated base terrain.
646                 content_t c_above = vm->m_data[vi + em.X].getContent();
647                 bool air_above = c_above == CONTENT_AIR;
648                 bool water_above = (c_above == c_water_source);
649
650                 // If there is air or water above enable top/filler placement, otherwise force
651                 // nplaced to stone level by setting a number exceeding any possible filler depth.
652                 u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
653
654                 for (s16 y = node_max.Y; y >= node_min.Y; y--) {
655                         content_t c = vm->m_data[vi].getContent();
656
657                         // Biome is recalculated each time an upper surface is detected while
658                         // working down a column. The selected biome then remains in effect for
659                         // all nodes below until the next surface and biome recalculation.
660                         // Biome is recalculated:
661                         // 1. At the surface of stone below air or water.
662                         // 2. At the surface of water below air.
663                         // 3. When stone or water is detected but biome has not yet been calculated.
664                         if ((c == c_stone && (air_above || water_above || !biome))
665                                         || ((c == c_water_source || c == c_river_water_source)
666                                                         && (air_above || !biome))) {
667                                 // Both heat and humidity have already been adjusted for altitude.
668                                 biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
669
670                                 depth_top = biome->depth_top;
671                                 base_filler = MYMAX(depth_top
672                                                 + biome->depth_filler
673                                                 + noise_filler_depth->result[index], 0.f);
674                                 depth_water_top = biome->depth_water_top;
675
676                                 // Detect stone type for dungeons during every biome calculation.
677                                 // This is more efficient than detecting per-node and will not
678                                 // miss any desert stone or sandstone biomes.
679                                 if (biome->c_stone == c_desert_stone)
680                                         stone_type = DESERT_STONE;
681                                 else if (biome->c_stone == c_sandstone)
682                                         stone_type = SANDSTONE;
683                         }
684
685                         if (c == c_stone) {
686                                 content_t c_below = vm->m_data[vi - em.X].getContent();
687
688                                 // If the node below isn't solid, make this node stone, so that
689                                 // any top/filler nodes above are structurally supported.
690                                 // This is done by aborting the cycle of top/filler placement
691                                 // immediately by forcing nplaced to stone level.
692                                 if (c_below == CONTENT_AIR
693                                                 || c_below == c_water_source
694                                                 || c_below == c_river_water_source)
695                                         nplaced = U16_MAX;
696
697                                 if (nplaced < depth_top) {
698                                         vm->m_data[vi] = MapNode(biome->c_top);
699                                         nplaced++;
700                                 } else if (nplaced < base_filler) {
701                                         vm->m_data[vi] = MapNode(biome->c_filler);
702                                         nplaced++;
703                                 } else {
704                                         vm->m_data[vi] = MapNode(biome->c_stone);
705                                 }
706
707                                 air_above = false;
708                                 water_above = false;
709                         } else if (c == c_water_source) {
710                                 vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
711                                                 ? biome->c_water_top : biome->c_water);
712                                 nplaced = 0;  // Enable top/filler placement for next surface
713                                 air_above = false;
714                                 water_above = true;
715                         } else if (c == c_river_water_source) {
716                                 vm->m_data[vi] = MapNode(biome->c_river_water);
717                                 nplaced = U16_MAX;  // Sand was already placed under rivers.
718                                 air_above = false;
719                                 water_above = true;
720                         } else if (c == CONTENT_AIR) {
721                                 nplaced = 0;  // Enable top/filler placement for next surface
722                                 air_above = true;
723                                 water_above = false;
724                         } else {  // Possible various nodes overgenerated from neighbouring mapchunks
725                                 nplaced = U16_MAX;  // Disable top/filler placement
726                                 air_above = false;
727                                 water_above = false;
728                         }
729
730                         vm->m_area.add_y(em, vi, -1);
731                 }
732         }
733
734         return stone_type;
735 }
736
737
738 void MapgenValleys::dustTopNodes()
739 {
740         if (node_max.Y < water_level)
741                 return;
742
743         v3s16 em = vm->m_area.getExtent();
744         u32 index = 0;
745
746         for (s16 z = node_min.Z; z <= node_max.Z; z++)
747         for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
748                 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
749
750                 if (biome->c_dust == CONTENT_IGNORE)
751                         continue;
752
753                 u32 vi = vm->m_area.index(x, full_node_max.Y, z);
754                 content_t c_full_max = vm->m_data[vi].getContent();
755                 s16 y_start;
756
757                 if (c_full_max == CONTENT_AIR) {
758                         y_start = full_node_max.Y - 1;
759                 } else if (c_full_max == CONTENT_IGNORE) {
760                         vi = vm->m_area.index(x, node_max.Y + 1, z);
761                         content_t c_max = vm->m_data[vi].getContent();
762
763                         if (c_max == CONTENT_AIR)
764                                 y_start = node_max.Y;
765                         else
766                                 continue;
767                 } else {
768                         continue;
769                 }
770
771                 vi = vm->m_area.index(x, y_start, z);
772                 for (s16 y = y_start; y >= node_min.Y - 1; y--) {
773                         if (vm->m_data[vi].getContent() != CONTENT_AIR)
774                                 break;
775
776                         vm->m_area.add_y(em, vi, -1);
777                 }
778
779                 content_t c = vm->m_data[vi].getContent();
780                 if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
781                         vm->m_area.add_y(em, vi, 1);
782                         vm->m_data[vi] = MapNode(biome->c_dust);
783                 }
784         }
785 }
786
787
788 void MapgenValleys::generateCaves(s16 max_stone_y)
789 {
790         if (max_stone_y < node_min.Y)
791                 return;
792
793         noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
794         noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
795
796         PseudoRandom ps(blockseed + 72202);
797
798         MapNode n_air(CONTENT_AIR);
799         MapNode n_lava(c_lava_source);
800         MapNode n_water(c_river_water_source);
801
802         v3s16 em = vm->m_area.getExtent();
803
804         // Cave blend distance near YMIN, YMAX
805         const float massive_cave_blend = 128.f;
806         // noise threshold for massive caves
807         const float massive_cave_threshold = 0.6f;
808         // mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
809
810         float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
811         float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
812         bool made_a_big_one = false;
813
814         // Cache the tcave values as they only vary by altitude.
815         if (node_max.Y <= massive_cave_depth) {
816                 noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
817
818                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
819                         float tcave = massive_cave_threshold;
820
821                         if (y < yblmin) {
822                                 float t = (yblmin - y) / massive_cave_blend;
823                                 tcave += MYSQUARE(t);
824                         } else if (y > yblmax) {
825                                 float t = (y - yblmax) / massive_cave_blend;
826                                 tcave += MYSQUARE(t);
827                         }
828
829                         tcave_cache[y - node_min.Y + 1] = tcave;
830                 }
831         }
832
833         // lava_depth varies between one and ten as you approach
834         //  the bottom of the world.
835         s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
836         // This allows random lava spawns to be less common at the surface.
837         s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
838         // water_depth varies between ten and one on the way down.
839         s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
840         // This allows random water spawns to be more common at the surface.
841         s16 water_chance = MYCUBE(water_features_lim) * water_depth;
842
843         // Reduce the odds of overflows even further.
844         if (node_max.Y > water_level) {
845                 lava_chance /= 3;
846                 water_chance /= 3;
847         }
848
849         u32 index_2d = 0;
850         u32 index_3d = 0;
851         for (s16 z = node_min.Z; z <= node_max.Z; z++)
852         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
853                 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
854                 bool air_above = false;
855                 bool underground = false;
856                 u32 index_data = vm->m_area.index(x, node_max.Y + 1, z);
857
858                 index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X);
859
860                 // Dig caves on down loop to check for air above.
861                 for (s16 y = node_max.Y + 1;
862                                 y >= node_min.Y - 1;
863                                 y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) {
864                         float terrain = noise_terrain_height->result[index_2d];
865
866                         // Saves some time.
867                         if (y > terrain + 10) {
868                                 air_above = true;
869                                 continue;
870                         } else if (y < terrain - 40) {
871                                 underground = true;
872                         }
873
874                         // Dig massive caves.
875                         if (node_max.Y <= massive_cave_depth
876                                         && noise_massive_caves->result[index_3d]
877                                         > tcave_cache[y - node_min.Y + 1]) {
878                                 vm->m_data[index_data] = n_air;
879                                 made_a_big_one = true;
880                         }
881
882                         content_t c = vm->m_data[index_data].getContent();
883                         float d1 = contour(noise_cave1->result[index_3d]);
884                         float d2 = contour(noise_cave2->result[index_3d]);
885
886                         // River water is not set as ground content
887                         // in the default game. This can produce strange results
888                         // when a cave undercuts a river. However, that's not for
889                         // the mapgen to correct. Fix it in lua.
890
891                         if (c == CONTENT_AIR) {
892                                 air_above = true;
893                         } else if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
894                                 // in a cave
895                                 vm->m_data[index_data] = n_air;
896                                 air_above = true;
897                         } else if (air_above && (c == biome->c_filler || c == biome->c_stone)) {
898                                 // at the cave floor
899                                 s16 sr = ps.range(0,39);
900                                 u32 j = index_data;
901                                 vm->m_area.add_y(em, j, 1);
902
903                                 if (sr > terrain - y) {
904                                         // Put dirt in caves near the surface.
905                                         if (underground)
906                                                 vm->m_data[index_data] = MapNode(biome->c_filler);
907                                         else
908                                                 vm->m_data[index_data] = MapNode(biome->c_top);
909                                 } else if (sr < 3 && underground) {
910                                         sr = abs(ps.next());
911                                         if (lava_features_lim > 0 && y <= lava_max_height
912                                                         && c == biome->c_stone && sr < lava_chance)
913                                                 vm->m_data[j] = n_lava;
914
915                                         sr -= lava_chance;
916
917                                         // If sr < 0 then we should have already placed lava --
918                                         // don't immediately dump water on it.
919                                         if (water_features_lim > 0 && y <= cave_water_max_height
920                                                         && sr >= 0 && sr < water_chance)
921                                                 vm->m_data[j] = n_water;
922                                 }
923
924                                 air_above = false;
925                                 underground = true;
926                         } else if (c == biome->c_filler || c == biome->c_stone) {
927                                 air_above = false;
928                                 underground = true;
929                         } else {
930                                 air_above = false;
931                         }
932                 }
933         }
934
935         if (node_max.Y <= large_cave_depth && (!made_a_big_one)) {
936                 u32 bruises_count = ps.range(0, 2);
937                 for (u32 i = 0; i < bruises_count; i++) {
938                         CaveV5 cave(this, &ps);
939                         cave.makeCave(node_min, node_max, max_stone_y);
940                 }
941         }
942 }