The noise from Terrain from Noise gives hills that are all about the same height. What's missing are wide plains and sharp peaks. You don't need a different noise for that. You reshape the same numbers after they are computed.
The map is on the left, top right are the height curve and a histogram of the heights, below it a cross-section along the dashed row on the map. The five nodes of the curve can be dragged with the mouse, dragging the map pans the view, and hovering the map picks the row for the cross-section. The chips switch curve shapes, terraces, ridges and the naive variant. The demo starts with the "Valleys" curve and ridges on. Chip 1 is the straight line, and then the map shows the plain noise from before again.
A curve between noise and picture
Every height goes through a function that maps 0 to 1 onto 0 to 1. With a straight line nothing changes. If the curve sags, the middle heights slide down and a big part of the map goes flat. Red Blob Games explains this at length with pow(e, exponent), and that is the easiest way in. I wanted to draw the curve and grab it, so here it sits on five nodes. Between the nodes runs a cubic polynomial whose slopes are chosen so that rising nodes never produce an overshoot (Fritsch and Carlson):
c.m[k] = d[k - 1] * d[k] <= 0.0 ? 0.0 : 2.0 * d[k - 1] * d[k] / (d[k - 1] + d[k]);
d are the slopes of the secants between the nodes. If it changes sign or one of them is 0, the slope at the node becomes 0, otherwise the harmonic mean applies. On top comes a rule for dragging: a node may not pass its neighbors.
const double lo = i == 0 ? 0.0 : y[i - 1]; const double hi = i + 1 == y.size() ? 1.0 : y[i + 1]; y[i] = std::clamp(value, lo, hi);
Without that clamp a higher value could sit left of a lower one. The curve would reverse and the map would be upside down at that spot: valleys suddenly higher than the slopes before them. The test for it is calculated by hand. The node values 0, 0, 0, 1, 1 give an S between the third and the fourth node, and its middle sits at exactly 0.5.
The histogram shows what the curve does to the distribution. The outlines are the heights before the curve, the filled bars after it. With "Valleys" (x squared on the nodes) almost everything moves left, in the start state 76 percent of the area is land, with the sea at 0.15. The peaks stretch upwards in return, because the top end of the curve is steep. Chip 3 is an S-curve: plains at the bottom, plains at the top and a steep slope in between.
Terraces
Rounding heights to steps is one line, round(e * n) / n (Red Blob has it too). The result is nothing but vertical cliffs. A slope you could walk up doesn't exist in that function. So I let every step consist of a flat tread and a sloped piece in the middle:
const double t = h * steps; const double level = std::floor(t); const double half = 0.5 * clamp01(riser); return (level + smoothstep(0.5 - half, 0.5 + half, t - level)) / steps;
riser is the share of the step that is slope. At 0 you get the hard cliff, at 0.35 (the value in the demo) something that looks like a farmer's terrace. In the middle of every riser the result equals the input, so the overall rise of the terrain survives. Calculated by hand for four steps and riser 0.4: at 0.375 you get 0.375. Chip T turns terraces on, chip S picks the number of steps. The orange line in the curve shows what is left after the terraces. Chip N for naive turns the slopes back into cliffs: on the map the shading disappears from the flat areas and the step edges become hard lines.
Ridges
Ordinary noise is round on the summits. Sharp crests appear when you lift the zero crossings of the noise:
const double r = 1.0 - std::fabs(n); ridgeSum += amp * r * r;
Where the noise crosses 0, r is 1 and everywhere else it is smaller, and the square sharpens the edge. Red Blob Games weights the higher octaves with the value of the first one, so only the mountains get the extra noise. I built it differently: the ridge field is added onto the smooth height through a mask that starts at height 0.5 and is fully on at 0.8:
const double weight = s.naive ? 1.0 : ridgeMask(base); return clamp01(base + weight * (clamp01(ridge) - 0.5) * kRidgeAmount);
With ridgeMask as smoothstep(0.5, 0.8, h). The ridge field is centered on 0.5, so it only lifts and lowers details, and on average the terrain stays as it is. R turns it on, with N it acts everywhere, valleys included, and the plains get criss-crossed by creases.
My first version had a bug that I only noticed from the number under the map. The highest point sat between 0.48 and 0.54 for all six seeds (back then "Valleys" was still x to the power of 2.5), although the smooth noise gets above 0.9 for every seed. I had built the ridge field from all octaves, the first one included. The first octave shapes the big hills, and a summit is where the noise is large, so |n| is large and r is small. The ridges pulled every summit down. Now the sum leaves out the first octave as soon as there is more than one. After that the highest point, with the current curve, is between 0.92 and 1.00.
Pitfalls
The input of the curve has to be in 0 to 1. pow with a negative base and a fractional exponent gives NaN, and a NaN that later gets converted into an index is undefined behavior. The test covers the edges too: values below 0 and above 1 are clamped before the curve, NaN becomes 0. The constants that stretch the raw noise are fixed in the code and not computed per picture from minimum and maximum, otherwise the map would flicker while panning. And terraces belong after the curve, not before it, otherwise the curve moves the step heights again.
The code is in the repo under terrain-shaping. The project Game Dev Snippets collects all demos of the series.