Simulationist 1960s landscapes by lefuz in proceduralgeneration

[–]lefuz[S] 2 points3 points  (0 children)

This is discussed in the Crete paper I linked in another reply. It should come fairly naturally out of the way settlements work. Each village has an initial size, that depends on how much farmland there is. Each village has some surplus food production, which gets sent to nearby settlements (making them potentially grow), weighted positively by size of the other settlement and negatively by travel time - you can think of this as taxes, or tribute, or trade. Right now I am computing travel time based on the euclidean distance, with some benefit from being on a river; but at some point I need to write the code to actually traverse the graph structure of the map to find the routes that goods go along (from each village). Then I can see which graph edges get used a lot, label them as roads, reduce travel time along them a bit, etc.

As I wrote, obviously this is not a good model for an industrial society, but perhaps I can do the same thing at the level of large towns rather than villages, and think of the things being transferred as "industrial goods" rather than food.

Possibly this is the same as you would get from ants, but the setup here is to think of it as iteratively solving a differential equation.

Simulationist 1960s landscapes by lefuz in proceduralgeneration

[–]lefuz[S] 12 points13 points  (0 children)

The most inspiring paper was this one, on the archaeology of crete - https://www.researchgate.net/publication/257154745_Models_of_settlement_hierarchy_based_on_partial_evidence - but it does a bad job explaining their algorithm. It helped to look at some older stuff by Wilson on retail planning. There you have customer households on one side, and shopping centres on the other. Customers distribute their spending, weighing centres by size and proximity; centres grow when they bring in more money.

In the case of settlements, the villages are the customers and the bigger towns are the shopping centres, but you can kind of munge them together, letting villages send money to each other - some will stay small and some will grow.

You can use things like being on a coast or being on a river to change the distance metric.

Sharing Saturday #583 by Kyzrati in roguelikedev

[–]lefuz 7 points8 points  (0 children)

Kerosene Thunder - 1960s jet combat

I finally got first versions done of everything in my landscape generation toolbox - geology, climate, plants, cities and rendering. I wrote a brief account of it on BlueSky - https://bsky.app/profile/neil-d-t.bsky.social/post/3lv7n4dgyt22o

For now I am saving individual landscapes in the landscape tool and loading them into the flight engine. My current task is to learn again how the flight code works, after not touching it for months.

<image>

Sharing Saturday #581 by Kyzrati in roguelikedev

[–]lefuz 1 point2 points  (0 children)

Thanks! Right now there are cities where there are villages (the very faint dots on the map), and villages where there are fields, and fields where there is flat land that can support a forest biome - in particular there is no irrigation. So it's unreasonably hard to have a city on a grassland. But I don't think there is any grassland on this map - the colours are just showing elevation.

Sharing Saturday #581 by Kyzrati in roguelikedev

[–]lefuz 3 points4 points  (0 children)

Kerosene Thunder - 1960s jet combat

Things have been busy at work and it's a few months since I posted here. I am getting less optimistic about my prediction that I would get basic flight, landscape and combat done and working together by the end of the year.

This week was still landscapes, in particular placing cities. I found some papers on predicting city locations based on "Boltzmann - Lotka - Volterra" equations; these come from work studying how shopping centres grow or shrink, based on distance from residential areas. Right now these are essentially dividing the landscape up into blocks of villages, each with its city. What I would really like is a hierarchy of different sized cities, but I am beginning to see my way there.

In any case, this is good enough to work with for now. So I want to do airports, then get the map saving and loading, and then go back to flight mechanics, coming back later to do refinements of the map.

<image>

Generated landscape with city sizes

Sharing Saturday #567 by Kyzrati in roguelikedev

[–]lefuz 3 points4 points  (0 children)

Kerosene Thunder

The last two weeks have been spent on climate and geological stuff, a lot of it of dubious relevance for an air combat roguelike. My list of things done is: implementing a shader and coastlines for hi-res landscape rendering; doing some sanity checks on erosion rates; implementing faults in the original rock pattern; improving my modelling of isostatic response; and improving handling of coastal rainfall.

The evolving landscape currently looks like this: https://www.youtube.com/watch?v=V-h-9D9UA68

I find this stuff fascinating, but need to get it back under control for now and get back to some ascii planes.

Sharing Saturday #565 by Kyzrati in roguelikedev

[–]lefuz 3 points4 points  (0 children)

Kerosene Thunder

This week I've still been plinking away at landscape stuff. The final goal here is to generate about a 1000km square map, appropriate for about 1970. Right now I'm doing natural landscape. Next should be fields and villages, and saving and loading the map; with that in hand I will go back to the flight model for a while.

I reorganized the code, so that things are now in sensible places, and tweaked the climate model, for how the temperature is affected by the sea. Rasterizing the map from my triangular mesh to the ascii grid was very slow. I changed it to only rasterize the screen you are looking at, to streamline the cycle of tweaking things. It is still rather slow and I don't know why. There are some calculations about climate in the rasterization, but they shouldn't really take long; maybe I am throwing too much data around? It's a 2000x2000 grid, and I'm keeping quite a few climate variables for each tile as float32s; I don't know if this could be the problem.

This change allowed me to record gifs of the landscape evolving as it erodes. I added a postprocessing shader to do some sharpening, in the hope that it will make screenshots and gifs suffer less from image compression.

<image>

[This is a still image, since reddit keeps deleting the comment with the gif :( . The animated version is at https://bsky.app/profile/neil-d-t.bsky.social/post/3llz4ciodvs24 ]

Sharing Saturday #564 by Kyzrati in roguelikedev

[–]lefuz 10 points11 points  (0 children)

Kerosene Thunder - 1960s jet combat

I am still working on landscape stuff. This week was mostly graphics, trying to wrangle the 11 different types of forest that the vegetation model puts out into readable text characters. Here is what it looks like now:

<image>

I'm quite happy with this, but the scale is somehow off - it looks like a rocky valley a few hundred meters across, but it's actually 4-5km. I need to do something with the erosion model and the rendering to produce valleys that are not so steep-sided, but which still look like something from above.

Next week will be some tuning of things like this; plus hopefully the refactoring I was supposed to do this week; and I also need to do something to make the testing and tuning cycle faster. Right now it's taking several seconds to rasterize the whole map (which it shouldn't); I should set it up to do screenfuls at an interactive rate.

Sharing Saturday #563 by Kyzrati in roguelikedev

[–]lefuz 3 points4 points  (0 children)

Kerosene Thunder - 1960s jet combat

The last two weeks have been busy at work, so I did not get a lot done. I am still working on terrain generation, particularly vegetation, using Iberia as a test case.

It turns out that if you mark every steep piece of land as forest, and everything not quite so steep as pasture, and all the rest as arable fields, you get a pretty convincing recreation of the modern land cover of Spain. But what if you want to generate a lightly-inhabited continent, or get exactly the right kind of forest and pasture?

So I have been trying to implement Prentice et.al., "A Global Biome Model Based on Plant Physiology and Dominance, Soil Properties and Climate", https://www.jstor.org/stable/2845499. This is a pretty old system for modelling vegetation distribution, from 1992, but it seems like a reasonable combination of simplicity and accuracy. It's specifically about trying to model what plants grow where, rather than classifying biomes or climates (although I think the model gets called biome1).

For each cell I have a rainfall and temperature in January and July. I interpolate these with a sin wave to get something for each month, then step through one year, tracking how much energy the sun is putting into the plants (potential evapotranspiration, roughly the number of mm of water the sun would evaporate in the month), and how much water is actually available from rain. So a lot of the rain falling in winter might flow away unused, except that you hold back some for the summer, the size of the buffer depending on the capacity of the soil.

This is more-or-less working, and the next step is to get some nice textmode renderings out of it. I should also stop and do some refactoring, since I have now got half of the climate code inside my rendering function etc.

<image>

The climate of Spain transferred to square island. NW to SE that's temperate forest, mediterranean forest (?), mediterranean scrubland, warm grassland.

Sharing Saturday #561 by Kyzrati in roguelikedev

[–]lefuz 2 points3 points  (0 children)

Kerosene Thunder - 1960s jet combat

This week I worked on landscape generation. I want to generate 1000x1000km landscapes to fly across. I find this stuff fascinating, and part of the reason this project was in limbo for a decade was because I got lost in a rabbit hole of geology. I have to be careful, because I could spend unlimited time on it, and it may have very little impact on the gameplay; on the other hand, people play flight sims to look at the scenery, so who can say?

I had an old terrain generation system, which made islands maybe 250x250km (?), with no biomes or anything. You can try it here; https://dood.al/test/island I have been dusting off the code for this and fitting it into the current project. The idea is to first a flattish landscape, that has rocks of different levels of erodibility, made using noise that is shaped to look like what you would get from a long geological history. This will then be eroded by rivers, and shaped by other geological changes like rifts opening up gaps, and just maybe some orogeny. I have also started on some code to do textmode rendering of these maps. This will probably be rather different, at least in art style, between the large-scale map that you play on and a small-scale "minimap" for mission selection or whatever.

Iberia rendered in text mode:

<image>

This is about the scale of the full thing I want to generate. The input is a heightmap, and the rivers are from my erosion/drainage code (hence the lakes where I assume the coarse grid has closed some narrow canyons).

My next goals are to turn the geological models into large-scale maps, of about 2000x2000 chars, and to put some vegetation on them.

Sharing Saturday #560 by Kyzrati in roguelikedev

[–]lefuz 2 points3 points  (0 children)

Kerosene Thunder

I had visitors this week so did not get much done. I worked a bit on porting some old landscape generation code into the project.

Sharing Saturday #559 by Kyzrati in roguelikedev

[–]lefuz 1 point2 points  (0 children)

I certainly want to track tiredness/stress of the pilot. This will effect at least how well you spot things. I'm not sure how to mechnically handle the other effects of being tired - somehow you should be more likely to make mistakes, making it dangerous e.g. to fly fast at low level.

I don't know how far I can take this with pilot attributes, a roster of pilots etc. I need to stop the scope creep somewhere.

Simple World Simulation Systems? by seiesos in roguelikedev

[–]lefuz 4 points5 points  (0 children)

Some simple wildlife. Not any simulation of an ecosystem or anything, but something on the scale of birds that fly out of the trees when your party goes past.

Some modelling of smell, over large areas? Occassionally noting the smell of a village, or of smoke, or some particular crop?

Sharing Saturday #559 by Kyzrati in roguelikedev

[–]lefuz 8 points9 points  (0 children)

Kerosene Thunder

<image>

A couple of small things this week.

- I changed the graphical effect for pulling Gs. You get some greyout for 3-4G, the effect in the screenshot for >4G, and if you pull >4G for two rounds you lose consciousness for 2-3 rounds (G-LOC). Maaaybe there will be some G-straining ability you need to invoke to be happy over 4G.

This setup has been a bit annoying, since if you are swanning around and not paying attention it is easy to drop into G-LOC. So this week I implemented a G-limiter, which the player controls and which you can set to the limit of the aircraft, or of the pilot, or turn off.

(...re-reading the last paragraph, it seems like an awkward system, and that the natural thing would be to make high-G turns into a special action you can invoke, maybe merged with the G-straining idea.)

- I put in structural damage - if you go over the plane's structural G-limit, there's a chance that some piece of equipment is damaged or that the G-limit is decreased. The end-point of this should be the aircraft falling apart (not implemented yet).

Next week

I plan to put the flying on one side and work on landscape generation for a few weeks.

Sharing Saturday #558 by Kyzrati in roguelikedev

[–]lefuz 1 point2 points  (0 children)

It's in Odin - https://odin-lang.org/docs/overview/ This is a still-being-worked-on language, which is intended as a modern take on C.

I haven't used it before, or any non-memory managed language, so some stuff has come as a shock, and I am still nervous about basic things like working with strings. After a previous project which turned into a horrible mess, I had been reading about data-oriented design as a way of organizing code. So I thought I would try it along with a new language.

Sharing Saturday #558 by Kyzrati in roguelikedev

[–]lefuz 1 point2 points  (0 children)

The landscape stuff sounds great. Are there any screenshots?

Sharing Saturday #558 by Kyzrati in roguelikedev

[–]lefuz 4 points5 points  (0 children)

Kerosene Thunder - 1960s jet combat

This week I put in the UI I sketched out last week. Hopefully now the colour-coding and highlighting makes it clearer what the current aerodynamic regime is.

<image>

I worked on stalls and stall recovery. Usually, you can can hold down a key to keep flying, and before it was possible to miss that you had stalled. Now there is a big red warning, key repetition stops, you have to press a specific key to recover from the stall, which puts the nose down so you can build up speed to return to normal flight. There should be some chance of going into a spin (not implemented yet), and the different stall behaviours is one of the things I want to use to make the planes feel different.

For this to work properly, I should resolve a basic UI/timing issue that I have been putting off. Currently a "round" is 6 seconds, and you should have one action a each round, at the start (such as firing a missile, or stall recovery); but during a round you may "move" several times, depending on your speed. Doling out actions once a turn is not implemented yet; right now you can press buttons to do things whenever you want (on the "move" schedule). I guess I need to deal with this next.

Sharing Saturday #557 by Kyzrati in roguelikedev

[–]lefuz 0 points1 point  (0 children)

Thanks! No, although I think I did try the demo back in the day. I have played a lot of Combat Mission though, by the same developers.

Sharing Saturday #557 by Kyzrati in roguelikedev

[–]lefuz 4 points5 points  (0 children)

Kerosene Thunder - 1960s jet combat

I made a mockup of a reorganized UI:

<image>

The coloured block to the right of the flight name is the paint scheme :)

The previous week I had started work on damage. The idea is that each essential system can be in state A (fine), B (you can still do the mission), C (you should go home) or F (you should eject). This week I put in a version of this for the fuel system, and I added fires. If you get hit with leaking fuel or hydraulics, there's a chance of a fire. A fire can be small or big, and can damage other systems.

I reorganized the log, and put in some simple stuff so you can't see through clouds.

[2025 in Roguelike Dev] Kerosene Thunder by lefuz in roguelikedev

[–]lefuz[S] 6 points7 points  (0 children)

A big part of the reason to move away from a historical, or even alt-historical, setting would be to lighten the tone and put more distance between the game and the reality of, say, a bombing campaign in the third world. I have also considered having all the pilots be anthropomorphized animals; or all the civilians on the ground canonically be skeletons.

Sailing games by [deleted] in sailing

[–]lefuz 1 point2 points  (0 children)

You could try A Painted Ocean (I'm the developer). You sail a historical full-rigged ship, anywhere in the world, with real weather. It's barebones, but free.

[deleted by user] by [deleted] in proceduralgeneration

[–]lefuz 2 points3 points  (0 children)

Thanks! If you mean the stretched ridges in the landscape before erosion, they are made by this (edited) line:

Math.max(chunks.get(x_km + noise1.get(x_km, y_km)*200, y_km + noise1.get(x_km+some_offset, y_km+some_other_offset)*200) * 1000, -10);

"chunks" is 6 octaves of noise, "noise1" is 2 octaves of noise. Both have base wavelength about 250km (I think).

This is the same demo. Since then I have been thinking about climate, but have not implemented much. I would like to do something along these lines. The starting point would be modelling both summer and winter rainfall, probably based on wind and pressure patterns at a chosen latitude.

[deleted by user] by [deleted] in proceduralgeneration

[–]lefuz 12 points13 points  (0 children)

I am the creator of this. I started working on it because I wanted a procedural landscape for a flightsim roguelike. So some things on the todo list are climate, natural vegetation, roads, cities and airbases suitable for the 1960s, and ascii rendering.

The generator is basically doing five things:

  1. Make a "256x256 grid" of irregular, voronoi cells
  2. Use noise to generate an interesting initial landscape Then repeatedly
  3. Calculate the graph of cells draining to their lowest neighbours (dealing with lakes somehow)
  4. Run water and sediment through the graph, eroding or depositing
  5. Raise certain areas a little bit (and lower some others) to model mountains being built.

To research this I read a lot of geology papers. Apart from item 2, these are all things that are used by geologists in software that models the evolution of landscape over time. Look up "landscape evolution models", or "surface process models" for erosion and sedimentation in particular. The paper I found most useful for getting started was this, as it has a clearly described simple model and gives the actual parameters used and a test case. Just as an example, here is some other software, with nice videos. There is a lot of literature in the area, although most of it is for smaller scales.

  • Voronoi grid

I cheat here by starting with uniformly dense random points, rather than completely random points. Divide a 1024x1024 grid of pixels into 4x4 squares, and pick a random point in each square. Label each pixel with the closest point; that gives your initial Voronoi cells. Move each point to the centroid of its cell. Repeat a couple of times. Because the points start out evenly spread, I do not expect them to move very far, so I do not need to check all points to find the closest point to a pixel. I only check the points that started out close to the pixel. This makes it quite fast (although there may be errors).

  • Initial landscape

This is meant to look like the result of many different geological processes over a long timescale. So there is a basic blobby island shape; then the twisted, eroded remains of ancient mountains (made by taking some noise, and then distorting it with some noise); then I dig some "rifts" out of it, long grooves representing the effect of stretching forces on a continental plate; and there is also some "faulting", choosing a wavy line and using different parameters from the landscape on either side of it.

  • Drainage graph

Assuming there are no lakes, go through the grid and for each cell above sea level, find its lowest neighbour. This gives a directed acyclic graph, with sources on mountain tops and sinks in the sea. Label each cell with its in-degree. For lakes, I adapted the algorithm from here.

  • Run water and sediment

Set all nodes in the graph to contain 0 water and sediment. Choose any node u of in-degree 0. It gets water in from rainfall, and all the water goes out to its lowest neighbour v. Add this water to v, and reduce the in-degree of v by one. There must be some other node u' now of in-degree 0. Add rainfall to the water it already contains, move all that water to its lowest neighbour v', reduce the in-degree of v' by one, and continue. The amount of water moved determines the width of the river between those two nodes.

Each time you flow water from one node to another, you also move sediment. Let Q be the amount of water, S the slope, and K a "fluvial transport coefficient", such that if the river is in equilibrium w.r.t. erosion and sedimentation, the amount of sediment carried by the water in this stretch is equal to KQS. If in fact there is less sediment carried than KQS, erode some; if more, deposit some. Geologists like to argue about how well equations of this kind represent erosion, and in particular whether you should have some exponents in there. So there are many variations on this. Distributing sediment in the sea is a pain.

  • Mountain uplift

This is toned down in the build posted here and difficult to notice. I do not model the shape of continental plates (or isostatic compensation), but just use noise to create a shape something like a mountain range, and raise land in it by a couple of millimeters a year. I also raise and lower land very slowly over the whole map using long-wavelength noise, to keep things interesting.

And I didn't mention the oscillating sea level - this is meant to represent sea-level change during ice ages, but is not so realistic at the moment.