Home › Articles › Imperator: Invictus AI Dev Diary 1.9.1
Reworked AI decision making for buildings and inventions, introduced the Invention Relative Chance system, and improved city founding logic.
Hello there! I'm Anbeeld, best known for my previous modding work for Victoria 3, where I've been writing economy AI from the scratch and implementing a stockpile system. Nice to meet you!
As an avid Imperator: Invictus player, at some point this January I suddenly felt the urge to pay the team back with my labour, and was very much welcomed by the wholesome fellow modders. Unsurprisingly, improving the AI (which seemed dusty, frankly speaking) is where I ended up landing.
This patch there are 2 big systems where I cooked basically full reworks of AI decision making, which is buildings and inventions, along with some smaller changes. Both these systems work by the AI choosing one option out of many similar, which we can manipulate by setting certain AI weights to them.

When I was working with Victoria 3, I actually ended up completely disabling vanilla AI for internal country management, replacing it with my own implementation. This allows for much better control and can lead to impressive results, but is very intensive in terms of labor and performance, and thus leads to many headaches for other developers in the team and some unrest from the players.
But in Imperator the economy and adjacent systems are much less complex, and the same goes for the AI that controls it, which in the end makes it much easier for us to manipulate it into doing one thing rather than another. Shoutout to my fellow Victoria 3 AI modders, who went the path of adjusting AI weights and had a whole lot of fun with that, because of how many of them there are and their effects being quite soft.
After some initial testing I was able to conclude that big numbers are larger than small numbers, but most importantly that the Imperator AI realizes this as well.

This conclusion moved me out of AI programming to… human programming. Consider this. You have some hundreds of inventions, and you need to attach some AI weight to many or even most of them. You draw some big picture in your head and start working. For “just ok” inventions you set a weight of 100, then for “pretty good” it may be 200 already, with “very good” going somewhere into 500.
But then it doesn’t really work.

At first these values may seem both significant by themselves and having enough difference to guide the AI into choosing one or another, but for a randomized system that chooses from dozens of inventions every time they really are not. Absolute best picks having only 5 times higher AI value than just average ones means they don’t get chosen reliably at all in the system with so many variables.
And I don’t mean this as an insult to you, dear reader, because in fact this is the issue that I myself stumbled upon at first – as I haven’t worked with AI weights previously that much. Folks much stronger in anything math related than me probably figured it all out before I even started explaining, but for me it required some additional steps to find out the way around it.

So I moved my “pretty good” inventions into thousands, while the “very good” tier went over 9000 already. This ended up working reliably enough, but then I realized I’m sitting in front of invention files filled with magic numbers of various magnitudes.
Even I myself started to lose track of which values I consider to represent what tiers of invention importance. An outsider coming in a year later to fix something in my priorities or to add a new invention will be forced to spend quite some time to find out that AI weight of 500 is apparently quite a small one, and even more time to understand what value he should put in to represent the “pretty good” tier.
The simple AI weight system with absolute values means the weights are not tied to anything, other than possibly some idea in a brain of one person (red flag for maintenance), and they also have no limits, except for int64 max value or whatever Paradox used in this case. This makes things incredibly hard when we are talking about manually setting weights for dozens or even hundreds of cases.
The way you can fix this is by introducing some abstraction, a measurement system. Like rating movies by a scale out of 10 instead of giving The Prestige a rating of 500, then some 1000 to Inception, and ending up with 999999 for Oppenheimer a few years later, because you just need it to be higher than the previous ones, but you don’t quite remember which values you gave back then and have no time to check.

After some brainstorming I made up a system called relative chance. Imagine the AI has 20 inventions to choose from out of all the trees and stuff. Now imagine you want one particular invention to have a 35% chance to get chosen, like it’s a pretty good invention, not insane but still useful. To achieve this you just need to apply IRC 35% (which stands for invention relative chance) to it in a form of script value irc_35, which under the hood is a number generated by a formula that I’ll show you later:
ai_will_do = {
modifier = {
factor = irc_35
}
}
So the relative chance is basically how likely an option to get chosen if all the other options are at base AI weight. Naturally, it can’t be higher than 100%, and by default there are generated values using the step of 5%, with the exception of 99%.
Of course, if you would then add a second invention to the picture with e.g. IRC 75%, both of them being in the pool simultaneously means their actual chances to get chosen are lower than advertised. But there’s nothing bad about this, because we still reached our goal. AI weights that we apply this way are now limited to some scale based on probability, so it works well with choosing out of many options, and you can easily tell how large the value is relatively and globally.

This is of course just a fancy 1/x under the hood, as base AI weight is 1:
IRC x% = (poolSize - 1) / (1 - x / 100) - (poolSize - 1)
In the case of Invictus the pool size is actually hardcoded for performance reasons, e.g. for inventions I just chose a certain number similar to how many inventions you can usually choose from at any given time on average. This lowers precision against base weight options, but between multiple options with relative chance attached it stays pretty accurate, so we are fine with that.
For example, with a pool size of 20 the value behind IRC 35% would equal 10.2308, while IRC 75% would be 57. This is just a fraction of the scale, but there’s already a higher difference by multiplier than between 100 and 500 – which, coming back to psychology, a human could expect to be enough for representing the entire scale.
The value of IRC 95% is 361 here, 35.2857 times higher than IRC 35%. Considering that 35% does not translate to 100 from absolute values examples below, but rather something like 250, you would need to type a value around 9000 (literally) to get the same effect when operating absolute values. This would be a borderline uncomfortable thing to do, while with irc_35 and irc_95 it’s much simpler and clearer.
The entire endeavor actually started with the observed issue where AI countries haven’t picked inventions that give discipline bonuses almost at all, leading to significant disadvantage against players, as if there’s not enough of it already. This became my playground, and for a few days the AI was the most disciplined ever.

This approach, sadly, is not sustainable, because apparently there are other things to take care of as well. Economic inventions increase the income of AI countries and thus are very important. For monarchies Proscribed Canon is a huge assimilation boost – and the AI struggles a lot with it otherwise. Then there are a lot of lesser priorities: siege capability, special city buildings, additional army boosters like Auxiliary Recruitment and Divinely Guided, maximum research efficiency, Formulaic Worship, City (or Rural) Planning, culture specific trees, and many more.

The thing I like about the Imperator system is that you are not really meant to research all the inventions, on the contrary – you are limited to getting only a fraction of them in most cases. At the same time, you are not restricted with what exactly you will research, and there’s relatively easy access to most of the inventions, besides the ones at the very bottom. But this also means there are straight up more and less important inventions, based on what the country is strong at.
The other thing to consider is that AI is not as good at keeping research efficiency as high as possible compared to players, and it also won’t make good use of certain types of inventions. Because of this, it’s even more important to provide the AI with a clear separation between must-haves and clearly secondary priorities, for example inventions related to diplomacy and navy.

In the end I checked basically every invention in the game, deciding for each of them if they have particular importance for AI. But just giving some IRC to the invention itself is not enough. Instead in most cases it was distributed in the form of trees, where a target invention and all the inventions leading to it get the same priority. This way the AI gradually researches them, eventually reaching that very important invention – but also benefiting from all the others in the tree, of course.

At the same time I tried to avoid making it all strictly railroaded and min-maxed. While there are clear layers of priorities and certain trees will almost always get researched before the others, inside of these layers I tried to preserve a healthy bit of randomness. Every AI country knows that discipline and national tax are both very important, but the values attached to them are close enough so that some countries will learn more about war science, while others – more about that legal robbery, finishing these trees at different points of the game.
AI decision making for buildings works through weights as well, so I’ve used the same relative chance system described above, with the shorthand of BRC this time.
Many buildings had some conditional AI weights even before I touched anything, but they weren’t detailed much. I also brought a whole new philosophy with myself, so I ended up starting from scratch. The Invictus team helped me a lot with the vision, naturally, guiding me towards the end result we would collectively agree on.

Building system, as we have it in Invictus, is full of interesting choices, especially in cities. The most curious part of it is the “ratio” buildings: Academy, Court of Law, Forum and Mill. These affect the desired pop count of nobles, citizens, freemen and slaves respectfully, along with bonuses to their happiness and other modifiers. But the thing is, you can actually harm your country by making incorrect choices here.
The most obvious example would be overbuilding Mills in cities where most pops are integrated, or even worse, have noble rights. Skewing ratio towards slaves would mean losing research due to the amount of nobles and citizens getting reduced, but also having less levies, as slave pops don’t count towards them. Other ratio buildings have similar side effects, although not as strong as the ones of Mills. AI countries are a bit weak at research, so I made them prioritize building Academies when possible. If the territory’s culture can’t produce nobles, other options will be considered.

As you see, there’s plenty of decision making to be implemented for the AI already. But that’s just the start. You also have “modifier” buildings: Library, Training Camp, Market and Tax Office. These can further increase what the city is already good at, be it research or taxes or something else. But how do you achieve that in the first place? Right, through ratio buildings. Looks like the AI should build these first and only consider modifier buildings after that. And not just any, but focusing on the ones fitting what the city outputs the most already.

But then there are non-cities as well! And these are very important, as Mines and Farming Settlements will provide the country with more goods to trade, and for more expensive ones getting some extra of them may be even more important than building up the cities. It seems logical to secure higher treasury income before we’ll start spending it on all these fancy buildings for the nobility.

For tribes, non-cities are all they usually have – but don’t worry, the logic for other settlement buildings is provided as well. It’s pretty simple, to be honest, just like these buildings are themselves. We want the AI to build Slave Estates when there are important trade goods not suitable for Mine or Farming Settlement, or when there’s a lot of slaves in general. We want some Barracks here and there to raise manpower, but Tribal Settlements are handy as well for tribesmen-heavy territories.

Back to cities, the AI also got some knowledge on how and where to use unique buildings. Foundry is a good investment in cities producing expensive trade goods. Great Temple helps with speeding up pop conversion, so it has priority for cities where a large percent of pops don’t follow the state religion. Same goes for Grand Theatre and assimilation, and in this case it’s even more important, as assimilation is generally much harder and slower to do than conversion.
The logic for building forts sadly is hardcoded. There are some variables exposed to affect their placement, but it’s a completely different thing in a technical sense than all the other buildings, so I haven’t touched the forts for now. Maybe one day.

Instead, I’ve had a lot of fun with ports. It seems like the ports are the most annoying building in terms of logic, as it was the same in Victoria 3. There was even a patch where devs themselves made some mistakes around it, so the AI would constantly delete ports, making the great British Empire ruin itself without foreign interference. Luckily, there was a certain mod that had its own logic for all the building management and thus avoided the problem…but enough of that.
I’ve tried to implement conscious port management by AI countries, for the first time in the history of Imperator or something like that. First, they now want only 1 or 2 ports per state, depending on what percent of it is coastal, with the exception of every city also having a port, which may increase the total number of them per state. Everything else is getting deleted, fixing tribes having a gazillion ports one next to another as a byproduct of them doing some conquering of each other. This frees up building slots that could be used for more useful buildings, as well as some gold.

The non-city territories with trade goods suitable for Mines and Farming Settlement are now heavily considered in port logic as well, so the AI would avoid building ports in them when it’s possible. AI countries can now even delete the port to free up the building slot in such territories, if they know they are able to rebuild the port in some other less important territory of the same state.

The other important thing is high level ports. As you may know, medium ships require a level 3 port to build and repair them, while for heavy ships a level 5 port is needed. I’ve implemented a logic where AI countries want a certain amount of such ports, based on country size, and vulgarly named them “mega” and “giga” ports respectively in the code. The latter, a level 5 port, is on the table only for the countries that unlocked a military tradition that allows them to build heavy ships.

Everything else, mainly level 2 ports, is downscaled to level 1. While there are small benefits to having more port levels outside of thresholds, other buildings offer much higher reward for that same building slot, and most AI cities don’t have a lot of them.
Oh, for Rome’s sake…
Yes, all of this means making the AI play the meta quite a bit. But one could argue that’s basically synonymous with it being competent. We are not building some kind of machine learning model here that could analyse the game itself, so the only alternative is to provide the AI with the information about what’s gonna benefit it and under what conditions. It needs to be told that 5% discipline is just better than 1% global monthly food in almost all cases, or that Academies are good when you have low research efficiency; there’s no other way around it.

But it’s not a strict order or script. Both invention and building systems make use of randomness, so while some choices are heavily weighted to be picked over the others, there usually are multiple “good” choices at the same time, having equal or very similar relative chance values attached to them. This means there’s no strict order on how the things are done, so the AI country would end up making slightly different choices compared to other similar countries, and even to the same country in your next playthrough. The most rigid thing is ratio building choices, based strictly on territory culture and trade goods, but it’s still a dynamic decision making.
Yes, slightly is an important word here – it’s pretty unlikely that Rome will randomly ignore all the military inventions, though not impossible. But I’m not sure it would be a good thing for this to happen constantly, as it would return us to a feeling that the AI is just dumb, which is what I’m trying to avoid with my changes. Your AI rival enslaving half its core population by building Mills everywhere might look funny, but for me it wouldn’t be as satisfying to beat the opponent that isn’t trying his hardest.
There’s one more thing I’ve touched in this patch, which I generously called a “smaller change” in the beginning of the diary. During oh so many observer tests I’ve noticed that AI countries don’t seem to create many new cities. Turns out the way they do it is just some rarely fired event with not so detailed conditions.
To fix this, I’ve implemented a new script for that matter and presented it to the team. For some reason they didn’t like migratory tribes creating Mesopotamia 2.0 in Germany and asked for changes. Literally 1984.

In the end I added a lot of restrictions to the script, especially for tribes, so the amount of new cities won’t be much higher than before, although still noticeable. But the conditions behind choosing territories for them are much more well thought out now: steppes are prohibited (thematically and due to -50% population capacity), capital is the first priority, high amount of integrated population is more important than ever, losing trade goods should be avoided, coastal and river territories are considered high value, same goes for “good” terrain types, and more.

As a player you can expect some of the larger non-migratory tribal nations to turn their capitals into cities, and if they would reform into monarchy or republic – a few more territories will follow the case. Small non-tribal countries that don’t have a single city will also fix this problem of theirs as soon as they’ll be able to pay the price. But creation of cities is not allowed until all the existing ones are somewhat developed, so it won’t affect larger empires that much, though in the late game a certain degree of further urbanization will probably take place.
Don’t worry, it won’t… yet. Getting more useful inventions and buildings might make your late game fight with Rome a tad harder, but it’s only a part of what constitutes the power of AI countries.
For my taste, they don’t spend enough on buildings as of now, and thus are not fully benefiting from changes, but adjusting budget spending is an entirely separate issue that I haven’t touched yet, at all. Maybe I’m completely wrong and spending more on buildings will make them too weak militarily – no way to know without diving deep into adjusting and testing and then again.

There are also other issues like not keeping high enough stability, lack of proper law management, and even things like not manually moving pops into cities when it would be very beneficial. Grand strategy AI is a very complex problem.
But there’s only so much time for side projects like this, so for now, I limited the scope of my work to just a few systems so I could get them right. Hopefully I’ve succeeded at that at least, but I’m of course open to make adjustments in the patches to come based on your feedback, which I’ll be very interested in.
Thanks for reading! Looking forward to some more fun stuff in the future.