Overhaul of the pop system to increase game performance without changing the current user experience

  • We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.

Mller

Recruit
7 Badges
Jan 6, 2022
1
4
  • Crusader Kings II: Charlemagne
  • Crusader Kings II: The Republic
  • Crusader Kings II: Sons of Abraham
  • Cities: Skylines
  • Crusader Kings II: Conclave
  • Crusader Kings II: Reapers Due
  • Crusader Kings II: Monks and Mystics
TLDR;
Looking at the changelog of 3.2 and previous performance improvements it seems that most of the computational effort at each timestep is used to calculate "Pop"- related game rules/mechanics/optimizations. Big improvements to performance have been achieved by empire-wide logarithmic growth which basically caps the total population in the game and therefore reduces the computational burden for the late game.
This post tries to raise awareness that the representation of the current population seems to be computationally inefficient and how it proposes an improvement without affecting the current user experience. The main proposed idea is to avoid simulating single entities and assume instead that there is a large number of these entities represented by a floating point number.


Problem
Please keep in mind that I do not have any insight into the code of stellaris itself, however, it seems to be the case that there are computations regarding the population. For instance migration off a planet: Each single "pop" needs to be checked if it should migrate to another planet. Let N be the number of the total population on the considered planet and let M be the total number of planets in the empire. The calculations for migrations have to be performed with the complexity of O((M-1)N). In simple terms, each pop has to be checked if it should move to another planet and which one. This is especially computational heavy in the late game where you have a lot of pops and a lot of planets which makes the product of (M-1)N large. Similiar problems arise for fractions and jobs.

Suggestion
Instead of calculating operations/events for single "pops" consider the operation/event to be calculated for the whole population and applied to the whole population. This would of course require the game to not have any integer amount of pops that range between 1 and ~10 000 but instead to have a floating point number which could for instance represent a billion or more entities.
Let me illustrate that by the migration example:
Let K be the number of the same species with the same traits. For the whole population, the migration chance to each planet has to be calculated. The number of people migrating to planet X is then: Mirgration_Chance_to_X*Population_on_Planet.
The complexity of this example depends on the number of planets and the number of unique species. This results in a complexity of O(K(M-1)).
In the endgame, the number of K is way smaller than the number of pops N. And therefore fewer computations have to be performed.

Fractions can also be treated like the migration problem. Thus the complexity here can also be reduced.

For the user experience, the pop mechanic is especially interesting when it comes to jobs.
In the early, to mid-game, the user develops the planets and constructs buildings which is an interesting mechanic.
Often the user waits until a pop is finished and then constructs the building the pop should work in.
Treating pops as a floating point number the population on a planet should continuously grow. How fast is an open question (exponetial/logarithmic/linear etc).
As for the jobs, the assignment is done in the same way as it is right now. Everything is simply expressed as a percentage of the whole population instead of assigning an integer number of "pops". Disabling buildings could be for instance realized with a simple slider instead of clicking 25 times on a minus to disable your farms.

And so on...



I think that this could improve performance and also increase user experience. It would also allow to have a higher population count in terms of usage of Planets. Basically, this allows to max out each planet since the performance of the game does not depend on the number of "pops" anymore. The current logaritmic pop growth for instance does not allow to populate the ringworlds of a fallen empire in the endgame since it would otherwise break the game.

I hope my point got clear. Please let me know if something is unclear.
 
  • 2Like
  • 1
  • 1
Reactions:
This is the solution they adopted for Victoria 2 and 3, so they already know how to do it and it works very well IMO.

The real issue with Stellaris was that the devs initially designed the game to have far fewer pops. Planets were gridlike and each pop occupied and worked one slot as in the Civilization games, so planets had on average 17-18 pops. Also, at the beginning there weren't habitats, so the number of planets didn't explode in the late game. Only subsequently they switched to the current system based on abstract housing and jobs. Some say the old system was better. Personally I found it disappointing and far more shallow than the current one. However, at least it was more computationally manageable.

Now, there is probably too many parts of the code that depends on this "discrete pop" design philosophy, so it is unlikely that they will revise it. We can only hope for a better Stellaris 2 :)
 
  • 1
  • 1Like
Reactions: