I’m sure that you’ve done this, but searching ‘terrain generation’ on Google yields a lot of really good resources. That, and staring at the scripts that were once mystical magic to me is how I learned.
Obviously, noise is needed to produce randomness. In order to have the same terrain each time the game starts, the noise must be deterministic – producing the same output every time when called with the same input. It can’t just be pseudo random numbers. To accomplish this, a matrix of random numbers is saved and indexed, scaled, and summed in the noise function at runtime. Perlin noise (aka ‘classic’ noise) is what Roblox’s math.noise function uses. This function is also deterministic, can handle 3D if needed, and is very fast since it is written in c++, making it perfect for terrain generation.
The idea behind noise is that we use it to determine the height map for our generated terrain – the y value for each x/z pair. But noise, by its very nature, is very undeterministic and doesn’t represent predictable rolling hills by itself very well! Each x/z pair is completely independent of each other pair, and bares no resemblance or influence from adjacent pairs. So, someone came up with the idea a long time ago to assign one height map position once for every 10 units in the x/z axes. This resulted in the height map being the positions of hills/depressions. For the x/z pairs in between hills, the height of the nearest hills are interpolated. For example, a point at x/z <3, 7> would be influenced by the hills/depressions at <0, 0>, <10, 0>, <0, 10>, and <10, 10>. Since x is lower, the hills/depressions with 0 for the x coordinate have a stronger influence on <3, 7>. Since the z coordinate is closer to 10, hills/depressions with the z coordinate 10 also have a stronger influence. This means that <0, 10> has the most influence on the height of <3, 7>. There are many methods of interpolation, but the simplest is linear interpolation, which you may want to research.
The results after applying this stretching of the height map looks okay on its own, but most map designers desire not just rolling hills, but mountains and valley’s too. These can be created by creating another height map which is stretched even more, say every 1000 units, and has a much larger amplitude (height difference). Adding the hill/depression height map and the mountain/valley height map together yields a much more realistic looking terrain. This pattern of combining noise is common. Each height map can be called an ‘octave’ of noise, noise with edited frequency and amplitude which is added together with other octaves to produce noise which has the desired property of regions being lighter and darker because they are related and influenced by each other.
For more advanced terrain including features like biomes, noise can be generated which would be checked when the terrain is being generated. If the noise is above a specific value, then it will be a part of the designated biome. For cliffs, streams, and lakes, post processing can be performed. For a cliff, find adjacent points which have a sufficiently large height difference between them, and make that height difference slightly greater be determining which points are on the same side of the cliffs and increasing/decreasing their height. Then, instead of the point connecting directly together, make a point directly above the lower point, and make the higher point connect to it. Streams and lakes can be formed by sampling the height map and specific points, then checking the paths of least resistance. Where many droplets pass through, a steam will be. Where many collect and local minimums, a lake can be formed. These features can be stored for easy lookup instead of recomputation at runtime.
For islands, all that should be needed is to set the sea water level at a specific height that puts a desirable amount of land above water. There are other ways to go about it, but that is the simplest. Here is an example of how one person did it with an island mask applied to the resulting height map. The ‘Island Mask’ section is the important one, but the context is very helpful.