<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Yasno Games devlog</title>
<link href="https://yasno.games/devlog/"/>
<link rel="self" href="https://yasno.games/devlog/feed.xml"/>
<id>https://yasno.games/devlog/</id>
<updated>2026-10-24T00:00:00Z</updated>
<icon>https://yasno.games/favicon.svg</icon>
<entry>
<title>Water runs downhill</title>
<link href="https://yasno.games/devlog/water-runs-downhill/"/>
<id>https://yasno.games/devlog/water-runs-downhill/</id>
<published>2026-10-24T00:00:00Z</published>
<updated>2026-10-24T00:00:00Z</updated>
<author><name>Yasno Games</name></author>
<summary>The evening our last post went up, we deleted the rivers. Twelve days later they wind down their valleys. This is what they did in between.</summary>
<content type="html">&lt;p&gt;&lt;video src=&quot;https://yasno.games/devlog/water-runs-downhill/valley.mp4&quot; poster=&quot;/devlog/water-runs-downhill/valley.jpg&quot; autoplay muted loop playsinline aria-label=&quot;Sliding out over a wooded slope above a river winding along the valley floor, the valley opening onto a plain and mountains beyond&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Our last post ended with &amp;quot;the rivers went in this month.&amp;quot; That evening we
deleted them.&lt;/p&gt;
&lt;p&gt;They had a flaw nothing we added could reach. The old generator routed water
between points 525 tiles apart. It knew the ground&#x27;s height at those points
and nowhere else, so it assumed the ground ran straight from one to the
next, and wherever a ridge stood between two points, the river went over it.
In one stretch of the world we counted 20 places where a river climbed 16
metres or more.&lt;/p&gt;
&lt;p&gt;We had spent nearly four weeks on it by then, each fix laid over the last: points
moved onto the troughs between ridges, troughs published for the points to
find, a rule for where two streams meet. Every fix moved the climbs somewhere
else. By October 12 four layers of the generator existed only to make
rivers, and the rivers still climbed. We took out all four, 4,295 lines, and
started again from what a river has to do.&lt;/p&gt;
&lt;h2&gt;Rules first&lt;/h2&gt;
&lt;p&gt;We wrote the rules down before any code. A big river never climbs. A small
stream may climb a little. A hollow fills to its lip and spills over, so
lakes are welcome. And nothing gets checked by sampling the ground along a
river&#x27;s length, because the far view of the world can&#x27;t pay for it.&lt;/p&gt;
&lt;p&gt;Every generator we read that gets rivers right does it one of two ways.
Some build the terrain from the rivers, and the ranges grow around the
drainage. Others let a river own the ground under it, cutting it down to a
bed that only ever falls. Our ranges already come from colliding plates, so
our rivers had to own their ground.&lt;/p&gt;
&lt;h2&gt;Coarse to fine&lt;/h2&gt;
&lt;p&gt;The next day the world moved onto hex cells of seven sizes, each three times
finer than the one above, from cells 729 tiles across down to single tiles.
Water is routed at every size. The coarsest cells find the big rivers and
cut their valleys. Each finer size takes the rivers handed down to it, lays
them over its own ground, and finds the smaller streams between them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/valleys.jpg&quot; alt=&quot;Two maps of the same square of land around the haven. Left: blue streams branching into rivers, each in its own valley. Right: smooth ground with three faint straight lines and no valleys&quot; /&gt;&lt;/p&gt;
&lt;p&gt;On the left is the land around the haven, where new players start, on
October 13: streams branching into rivers, each in a valley of its own. On
the morning of the 14th it went into the game.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/floating.jpg&quot; alt=&quot;Water hanging in the air as a staircase of blocks up a rocky mountainside&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The water stood in the air. A river coming down a mountain hung over the
slope as a staircase of blocks, and more than half the wet tiles round the
haven held water above their own ground. Some of that was the generator and
some was how the game draws a river stepping down from one tile to the next.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/drowned.jpg&quot; alt=&quot;A world under water: translucent blue walls and sheets standing over cliffs and hills&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The drawing went first. A fall is now drawn only where the ground beyond the
water is lower, and the afternoon before that rule held, the world went
under walls of water.&lt;/p&gt;
&lt;h2&gt;Combs&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/comb.jpg&quot; alt=&quot;A plain below a slope, cut by a row of straight parallel streams like the teeth of a comb&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Then the rivers ran straight. Each size hands its ground down to the next as
flat sloping triangles, and water on a flat slope takes the one steepest way
down, the same way for every stream on it. A hex grid makes it worse: a
stream turns only where the ground beside it falls away faster than the
ground ahead, and on a smooth flank nowhere does. A mountainside&#x27;s streams
came out as the teeth of a comb.&lt;/p&gt;
&lt;p&gt;We tried roughening the ground, which changed nothing, and holding each
river to the line the coarse cells drew for it, which made rivers climb
again.&lt;/p&gt;
&lt;p&gt;Then we lost the valleys. We had made where a river starts depend on how
steep the ground is, and how hard it cuts on the rain its land gathers. The
haven is dry, gently sloping country, and around it the share of ground any
river had cut fell from 98% to none. That is the
right-hand map above.&lt;/p&gt;
&lt;p&gt;Rain was the wrong thing to read. Valleys are cut over thousands of years by
floods, and a dry country&#x27;s floods run as high for their land as a wet
one&#x27;s. A river now cuts by the land it drains, and rain decides only how
wide its water runs today. Around the haven, 84% of the ground came back
cut.&lt;/p&gt;
&lt;p&gt;The comb was still there. A level handed its rivers down as heights at its
own points, so any bend smaller than one of its cells was lost on the way
down, and the finer river sat in the straight groove the coarser one left.
Now a level hands down each river&#x27;s course whole, and the next size bends it
through the ground beside it, so a river picks up bends at every size. A
stream that starts on a plain wanders toward whatever lies lower, so streams
gather into trunks.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/straight.jpg&quot; alt=&quot;The world viewer&#x27;s render of a valley: one dead-straight river with straight tributaries joining it at angles&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/winding.jpg&quot; alt=&quot;The same valley in the world viewer: the river winds down the valley floor, its banks curving with it&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That is one valley in our world viewer, which draws the generator&#x27;s tiles
without the game&#x27;s look: on October 22, then today.&lt;/p&gt;
&lt;h2&gt;Lakes&lt;/h2&gt;
&lt;p&gt;Lakes came last. A lake the coarse cells found in a wide basin used to
vanish at the tiles, because no small cell could see the whole basin, and
the lake dried to a flat disc.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/disc.jpg&quot; alt=&quot;The world viewer&#x27;s render of a broad flat dry disc of grass in a basin, rivers running round its edge&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So a lake is handed down like a river. The morning after that went in, this
was waiting.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/lake-wall.jpg&quot; alt=&quot;A broad lake that ends in a straight wall of water standing above the grass, in the rain&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Where a finer valley crossed the lake&#x27;s rim, the lake stood on at its old
level, a wall of water over the river that should have drained it. By nine
that morning each size was flooding every lake handed to it afresh from its
own ground, and the water standing round the haven fell from 22,848 tiles to
5,773.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/water-runs-downhill/ponds.jpg&quot; alt=&quot;A stream with small ponds along it at the bottom of a wooded valley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now a stream coming down a wooded valley fills a few ponds on its way.&lt;/p&gt;
&lt;p&gt;The rivers come from a generator: seeded code, no trained model, nothing
drawn by hand. Claude writes that code with us, and we decide what a river
should look like and throw out what isn&#x27;t one.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Seven mountain ranges</title>
<link href="https://yasno.games/devlog/seven-mountain-ranges/"/>
<id>https://yasno.games/devlog/seven-mountain-ranges/</id>
<published>2026-10-12T00:00:00Z</published>
<updated>2026-10-12T00:00:00Z</updated>
<author><name>Yasno Games</name></author>
<summary>We have built the mountains in our hex-tile MMO seven times. Here is what each one looked like, and where the seventh stands.</summary>
<content type="html">&lt;p&gt;&lt;video src=&quot;https://yasno.games/devlog/seven-mountain-ranges/range.mp4&quot; poster=&quot;/devlog/seven-mountain-ranges/range.jpg&quot; autoplay muted loop playsinline aria-label=&quot;Sliding out over a crest at dawn, looking down across a forested valley to ridge after ridge&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;We&#x27;re Yasno Games, and we&#x27;re making an MMO on a hex grid: an open world you
cross on foot, generated from a seed. The mountains in that picture are our
seventh go at a mountain range. The first six are gone, but git keeps
everything, so we went back through it to show you what they looked like.&lt;/p&gt;
&lt;p&gt;There are two kinds of picture here. The top-down maps are drawn from each
version&#x27;s own height code: 20 km of its world, all in the same light, one
colour for one height across all of them. Everything else is the game itself,
this month&#x27;s build unless the text says otherwise.&lt;/p&gt;
&lt;h2&gt;Noise, twice&lt;/h2&gt;
&lt;p&gt;The first ranges, in March 2024, were Perlin noise: a height for every tile,
read off a smooth random field. Noise makes hills. It never makes a range,
because a range has a direction, and noise has none.&lt;/p&gt;
&lt;p&gt;In October 2025 the noise got regions, and mountain regions got cliffs stepped
in strata.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://yasno.games/devlog/seven-mountain-ranges/terraces.mp4&quot; poster=&quot;/devlog/seven-mountain-ranges/noise.jpg&quot; autoplay muted loop playsinline aria-label=&quot;Walking among hexagonal columns stepping up a noise hill, February 2026&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;That is the second one in the game in February 2026, the week before it went:
every tile a hexagonal column, so a hill is a staircase of them.&lt;/p&gt;
&lt;h2&gt;Plates, then nothing&lt;/h2&gt;
&lt;p&gt;In February we started from tectonics. The world split into plates, each with
its own base height, their edges warped so they curve, and a ridge raised
where two plates push together.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/relief-plates.jpg&quot; alt=&quot;Relief map: terraces stepping between plates&#x27; base heights, crossed by one ridge along a plate boundary&quot; /&gt;&lt;/p&gt;
&lt;p&gt;What you get is terraces where one plate&#x27;s height meets the next, and one
ridge. Two days later we took the heights out and started modelling what lies
under the crust: denser and lighter provinces, hotspots, heat spreading from
them. Those were fields, and none of them was a height yet. For those weeks
the world in the game was flat.&lt;/p&gt;
&lt;h2&gt;Placing the mountains&lt;/h2&gt;
&lt;p&gt;In March we stopped deriving mountains and placed them. A continent grew a
spine of peak cones joined by ridgelines, and streams grew down from the
ridges, carving ravines as they merged. Over the summer an erosion stack went
on top: glacial cirques bitten into the shaded side of the high peaks, and
slopes shaped convex at the crest and concave at the foot.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/relief-spine.jpg&quot; alt=&quot;Relief map: a cluster of conical peaks up to 2.8 km with cirque bowls near the summits and ravines down the flanks, each cone&#x27;s round footprint visible on the plain&quot; /&gt;&lt;/p&gt;
&lt;p&gt;These are the tallest of the maps, up to 2.8 km, and they had a feel in the
game we liked.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://yasno.games/devlog/seven-mountain-ranges/spine-flyover.mp4&quot; poster=&quot;/devlog/seven-mountain-ranges/spine-peak.jpg&quot; autoplay muted loop playsinline aria-label=&quot;Turning above the top of a spine peak in the August build, the cone dropping to the coast all round&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;That is the view from the top of one, in the August build we rebuilt to film
it: the cone falling away to the coast on every side.&lt;/p&gt;
&lt;p&gt;From above you can see the problem. Each cone is a circle stamped on the
plain, and where two cones meet there is a straight seam. A placed mountain
does not know why it is there, so nothing around it agrees with it.&lt;/p&gt;
&lt;h2&gt;Letting them emerge&lt;/h2&gt;
&lt;p&gt;In September the plates came back as the source. Crust thickens where two
plates push together, and the height follows from the thickness. The spine,
the cirques and the slope shaping came out: about ten thousand lines of code,
deleted in one commit.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/relief-orogen.jpg&quot; alt=&quot;Relief map: one smooth swell of high ground with a single steep flank and no ridges or valleys inside it&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Thickness gives you a swell. It gives you no ridges, and no valleys inside it.&lt;/p&gt;
&lt;h2&gt;Sheets&lt;/h2&gt;
&lt;p&gt;Two days later we rewrote the plates themselves, and that is the seventh
range. Where one plate runs under another the crust stacks into sheets, the
way real fold-and-thrust belts are built.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/relief-thrust.jpg&quot; alt=&quot;Relief map: bands of parallel stepped thrust sheets running in straight lines with sharp 60-degree bends&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The plates were cells on a lattice, and the ranges followed the lattice:
straight runs, 60° corners. The next day every plate edge started being read
through a smooth warp, so coasts, fronts and ranges bend together and never at
a corner.&lt;/p&gt;
&lt;h2&gt;Walkable&lt;/h2&gt;
&lt;p&gt;That version had a problem you could feel. Most of the ground was walkable,
and the ridges, the part you came for, were almost all walls. A player climbs
one level per tile, and the faces were steeper than that.&lt;/p&gt;
&lt;p&gt;We could raise the step or lower the mountains. We lowered the mountains to
the angle loose rock actually rests at, 34°, with scree running out about 150
tiles from the foot of each range. That is still too steep to walk straight
up, so you climb across the face, the way you would a real scree slope.
Ground at 45° or steeper fell from 2.4% of land to 0.75%, and what stayed
that steep was mostly gorge walls, which is where you would expect a wall.&lt;/p&gt;
&lt;p&gt;For scale: a tile is about 1.7 m across and a level is 0.8 m. The geology is
Earth&#x27;s, squeezed so a range fits in a world you cross on foot.&lt;/p&gt;
&lt;h2&gt;What didn&#x27;t work this month&lt;/h2&gt;
&lt;p&gt;Ravines. We cut a gully down a range&#x27;s flank every 46 tiles, 17 levels deep.
In the game it was corrugated iron: a ridge every 80
metres, walking across it felt like waves, and the far view could not draw
it. It came out the same day.&lt;/p&gt;
&lt;p&gt;What did stay: a range&#x27;s crest now rounds off as fast as its height wears
down, trees thin out where the slope gets too steep to hold soil, old
collisions inside a continent leave worn-down belts instead of nothing, and
this month rivers started running along the troughs between ridges and
crossing at the passes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/trough-river.jpg&quot; alt=&quot;A river running down the trough at the foot of a ridge&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/relief-now.jpg&quot; alt=&quot;Relief map: a curving range of stacked thrust sheets between a lowland plain and a gullied plateau, the coast in one corner&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That is the range as it stands this month, its crest about 900 m above the sea.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://yasno.games/devlog/seven-mountain-ranges/crest-now.jpg&quot; alt=&quot;The snow on that range&#x27;s crest, the next sheet&#x27;s face beside it&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Where it stands&lt;/h2&gt;
&lt;p&gt;It isn&#x27;t done. Lakes have been tried three ways and taken out each time,
because they cost more to generate than they showed. The rivers went in this month.&lt;/p&gt;
&lt;p&gt;Every range here comes from a generator: seeded code, no trained model,
nothing drawn by hand. Claude writes that code with us, and we decide what
the mountains should be and throw away what isn&#x27;t it, six times so far.&lt;/p&gt;
</content>
</entry>
</feed>
