XaiJu
fantasytowngenerator
fantasytowngenerator

patreon


Development Update - October 2023

Hey everyone, hope you're all doing well. As I said in my last post, my main focus right now is to enable larger settlement options. Before that can happen, I want to reduce the costs of generation/simulation and the costs of storage, as well as make sure that most devices can render settlements that large.

I had an idea to try and speed up the generation, that also solves another problem I've been having - that it's really difficult to add a new building. 

TLDR; There is a new algorithm to decide which buildings to place, which has allowed me to add new buildings, and replace the old 'advanced settings' with much simpler 'buildings' settings in the create settlement form. And generation is slightly faster.

Overview

The algorithm Fantasy Town Generator uses to create the settlement maps can be split into two main steps: 

1. Generating the settlement: this creates the buildings and people that will fill the settlement. For example, it could generate some farms and some blacksmiths, with people employed at each.

2. Generating the map: this takes the list of buildings from the previous step, and generates a map that gives all of those buildings a location. 

The focus of this post is step 1, generating the settlement - specifically choosing what buildings (and how many) should be in the settlement. There are some desired properties for this generation:

The (old) resource demand algorithm

The generation algorithm for this used a resource demand model to emulate this behaviour. Each resident would create demands. Each placed building could satisfy demands, but also add new ones. The algorithm basically picked a building that would satisfy the biggest demand, repeating until the settlement reached the desired population. This worked! More demand could be created for common buildings, so more would be placed (satisfying the first property). As buildings could create demands, if a building was placed less, it would create less demand, so buildings satisfying that demand would also be placed less (satisfying the second property).

However, the resource demand model has some downsides. The first is that it's a reasonable amount of effort to keep track of the current demands, and which is the biggest. The second, is that it was horrible to maintain. Let's take an example. Say we want a very simple settlement with some tailors, weavers, and farms. Maybe we've done some research and we find that there should be roughly a 4:2:1 between farms:weavers:tailors. To set up the config for this generation, we might say: 

- Each person creates 1 demand for clothing.

- Each tailor satisfies 100 demand for clothing, and creates demand for 200 fabric

- Each weaver satisfies 100 demand for fabric, and creates demand for 100 cotton

- Each farm satisfies 50 demand for cotton.

With this config, I'd expect there to be 1 tailor, 3 weavers, and 6 farms per 100 people. That wasn't so bad - what's the problem? 

1. It's very difficult to reason about. Looking at just the tailor config, you have no idea how many tailors are going to be created. Looking at the weaver config, you have no idea what buildings it might be related to (though you could guess).

2. The demand priority is difficult to manage - as a building is picked to satisfy the highest demand, if the demands aren't properly managed, some buildings may never get placed as not enough demand was created - or not in the expected ratio compared to other buildings.

3. Each building needs a demand to satisfy. What if I want to add a pretty obscure building - e.g. a cabinet maker. Do I create a new demand for cabinets? Who creates demand for this - how much? Do I combine with an existing demand, like furniture? How do I control that I expect there to be more table makers than cabinet makers?

4. Shops. Each demand had a certain import amount. Once that import amount reached a certain threshold, a shop for that demand would be placed. E.g. once enough fabric was imported, a fabric shop would be created. This was one hard-coded threshold used for all demands, so based on the initial demand, some demands would have different ratios of shops, and not all shops were actually created.

In summary, it was a pain to maintain.

The new algorithm

The new algorithm is very similar in principle to the previous one, however the config has been drastically streamlined. Instead of being very detailed with each demand, buildings are now part of a group. For example, there is a group 'Tavern', which contains all the different tavern types. Each group has config to decide when one of the buildings should be placed. This is either done in terms of a population threshold, or in terms of other buildings. Writing the example above in the new config looks like:

- 1 farm per 25 people

- 1 weaver per 2 farms

- 1 tailor per 2 weavers

This is much easier to reason about, as you don't need to figure out where each demand comes from. It still satisfies the two desired properties - this chain has different ratios of buildings, and if there are fewer farms, there would be less tailors. This also means that I don't need to manage individual demands, and I don't have to deal with webs of demands (where multiple buildings satisfy/create different demands, and figuring out how they all interact). With this model, it's also much easier to manage the ratio of buildings within a group (e.g. the cabinet maker / table maker example above). Each group can just define the proportion of buildings placed within that group. Each group also defines shop alternatives that can be placed. In the UI, this looks like:

Clicking the 'Edit core buildings' button (for taverns as it's a better example):

Each option can have different lifestyles - this means that different config can be used based on the requested lifestyle (within the algorithm). This is mostly used for things like taverns - where an aristocratic tavern is more likely to be an 'Upper class tavern' vs a 'Raucous dive'. 

Clicking the edit button for a row:

Additional benefits

As it's now much easier to configure buildings, I added ~40 new ones. Additionally, buildings that I had poorly configured before that weren't getting placed, are now getting placed. Also, the simplification of the algorithm means that the overall generation runs about 8% faster.

Other changes

I've added a new person type - retired people. Before, people worked up to their max age. Now, elderly people will be retired. They behave similarly to the existing unemployed person type, however they won't try to be employed when buildings / districts are re-rolled. I also tweaked the age generation settings - there are now a more children than there were before (which was very very few). I also fixed some bugs around islands in rivers during generation.

Conclusion

I'm much happier with this new settlement generation algorithm, it should (fingers crossed) be much easier to maintain. Do you have any buildings you want to see added to the generation? let me know!

I think the next thing I tackle will be trying to improve the file size of the settlements. Family relationships is one of the biggest things that is stored at the moment (each relationship is a row in a table). I think I can improve this by just storing the parent/child relationship, and deriving the rest from that. As part of this I might also add a family tree view. There are also a few other things I want to try to reduce the file size. Anyway, watch this space.

As always, let me know what you think! Check out the discord if you haven't already, I'm usually around (https://discord.gg/aJx7ctezBj).

Comments

Always something new. Awesome

Shaun Booth

Please keep up the good work. This is a very unique thing you've created here.

William O'Braidislee


More Creators