1. Stellaris
  2. News

Stellaris News

Stellaris Dev Diary #240 - Scripting Improvements in 3.3

written by Caligula

Доступно на русском в ВК/Read in Russian on VK

Hello and welcome to another modding-based dev diary - as has become tradition in the weeks before releases in recent times. I fear that we may soon run out of ways to revolutionise the script system, but for now, there’s some pretty cool improvements we have to show off which will be making their debut in 3.3 (you can try them out early in the open beta).

[h3]Script Values[/h3]

This story starts with weight fields. With which I mean something that looks a bit like this:

    weight = {
base = 1
modifier = {
factor = 2
some_trigger = yes
}
}


We realised that the code underlying this script structure was not consistent: there were a number of distinct code implementations that varied in ways that were not readily obvious to the end user, the scripter. For instance, in certain ones, you could input “factor” or “add”, in others, “factor” or “weight”. Then there were the downright problematic cases: sometimes, when you set the base to 0, the game would read 1, and in one case (ai personalities) “factor” would actually count as “add”!

The solution here was to remove all the variations and consolidate them into one code implementation to rule them all. It would have to be made to incorporate the idiosyncrasies (except for the mentioned issues/bugs) of the existing versions (i.e. not break vast swathes of script), but on the other hand, having one system would allow for us to roll out improvements that could be used everywhere in the game.

Despite a few hitches at the start (I may or may not have accidentally had every anomaly capable of spawning on every planet, at one point), this proved quite achievable, so now we no longer need to worry about these fields working differently in different places. Basically the only variance left is whether their default value is 1 or 0.

This done, a few more things could be added to the system. For instance, why just have “factor”, “add” and “weight”? There are a lot of other mathematical operations out there. So we added subtraction, division, modulo, min, max, abs, and rounding (with round, floor, ceiling and round_to). We also made it no longer necessary to enclose these in “modifier = {}”, if they were meant to always apply rather than be triggered.

But that was just the start. Back in 3.1, we added the ability to use “trigger:” in lieu of a number in places such as this, to allow some more complicated maths (so it would take the result of the trigger e.g. num_pops could return 32 pops instead of an absolute number). The code behind this wasn’t quite ideal, though. Basically, whenever the game wanted to calculate what “trigger:num_pops” meant, it would take the string “trigger:num_pops”, see if it started with “trigger:”, if yes then shave that off, and then try and make a trigger from the remainder (and log an error if it failed). Unfortunately, this wouldn’t happen during startup, but rather whenever the game encountered this in script - for example, if it was needed to calculate a tooltip, it would be doing this every frame. Which made it annoying to debug and more potentially costly performance-wise than it needed to be.

This could be done better. So, for 3.3, we made a container called a “CVariableValue”, which could contain several objects:
  • An integer or fixed point (basically just a normal number)
  • A scope/event target - so you could refer to “owner.trigger:num_pops”
  • A trigger
  • A modifier definition
  • A variable string
  • A script value*


*I’ll get back to this later.

Basically, whenever the game would read a script value, it’d work out what it is on startup. This means that whenever the actual value is needed, it would not have to chop up the string and work out what is wanted, but it could simply give the value or call the trigger that is specified. Coincidentally, this system also made it vastly easier to roll out the ability to use “trigger:” in various places, so if there are more places where they’d be desirable, we really don’t have that many excuses not to provide them there (uh oh).

The modders amongst you will have noticed that there’s a few extra things we made possible along the way, there. Firstly, a quick win was to let you call “modifier:” in the same way as you’d call “trigger:”. Basically, if a pop had +20% citizen happiness modifiers applying to it, and you used “modifier: pop_citizen_happiness (without the space - :p is an emoji...)”, you’d get 0.2. The other thing we added was script values.

The idea for these came from newer PDS games, the Content Designers of which would taunt us with their games’ superior script maths capabilities. Basically, the gist of what made them powerful was being able to substitute a value for a key which would run a series of calculations on demand. So “my_script_value” could be 57 + ( 24 * num_pops ) / num_colonies, or something like that. With the already-mentioned changes, we were almost there, so we added a new thing (named after script_values and capable of many of the things they are capable of in our newer games, but actually sharing very little code, so the exact workings probably vary a bit).

These “script values” would basically be a weight field like that mentioned at the start of this section, which would be defined by key in a script_values directory, e.g.

leader_cost = {
base = 2
modifier = {
subtract = 6
num_owned_leaders > 5
}
modifier = {
add = trigger:num_owned_leaders
num_owned_leaders > 5
}
mult = 50
}


Then we could refer to it anywhere in the game via “value:leader_cost”, and it would calculate the value on demand. We are already finding this very useful in improving the game’s scripts - not only is it easier to get correct values with this, but we can also radically cut down on copy-pasted scripts in weight fields (job weights, I’m coming for you!). Conveniently, since script values are read in a similar way to scripted values and triggers, we can feed in parameters, e.g. value:my_value|PARAMETER|50| would have the game use the script value my_value where any instance of "$PARAMETER$" would be substituted with 50.

Even with all these changes, there were still a couple more we could make to the scripting language. The first was adding complex_trigger_modifiers to script_values and weight fields. Basically, these allow you to use the value of triggers too complicated to use with “trigger:”. An example would be this:

        complex_trigger_modifier = {            #fewer worlds => more menace from destroying one
trigger = check_galaxy_setup_value
parameters = { setting = habitable_worlds_scale }
mode = divide
}


This works with the same triggers that work with export_trigger_value_to_variable. We also added a few triggers to these: notably, all count_x script list triggers (e.g. count_owned_planet), and the “distance” trigger.

A comprehensive guide on all you can do with script values is attached to this post (and in common/script_values). To be honest, it’s hard to overstate the amount of things this new system system enables us to potentially do. For instance, in the example above, we scaled leader costs based on how many leaders you own. We also scaled Unity boosts with the Autochthon Monument based on how many ascension perks you have unlocked with this method. The list goes on and will continue to grow with each update we release.

[h3]Mod Overwriting[/h3]

Script values isn’t the only thing I can talk about today. Modders have long been a bit bemused by the different ways elements of the game handle overwriting. Specifically, by the way it varies. Unfortunately, they will probably continue doing so for a while yet, but since a bit of progress was made here, I felt it would be interesting to people to know why this sort of issue occurs.

Basically, when modders overwrite the vanilla files, they can either overwrite the entire file (which always works), or they can overwrite individual entries within the file, for example the “miner” job. When the game encounters a second entry that matches the key of an existing one, various things can happen:
  • It replaces the existing one perfectly (last read is used)
  • It replaces the existing one, but imperfectly, e.g. if you individually overwrite jobs, you can no longer refer to them in modifiers (not ideal)
  • The second entry is ignored (first read is used)
  • Both the first and the second entries are kept (duplication - not ideal)
  • It appends the information inside to the existing entry (special case for on_actions)


So, why are there these various behaviours? Basically, it is largely a matter of how the database is read in the C++ code.

When the game encounters script files, as a rule, it will read the object (e.g. miner = { }) and store that in a matching database (e.g. the job type database), which the game will use in various ways when it needs to do stuff with that matching object type. In the case of many of the oldest objects in the game (stuff that has existed largely in its current form since before release, e.g. technologies and ethics), they would be coded in as an object in a custom-made database. Since the code for reading this database would be written afresh (or copied) each time a new object was defined, both the order in which it would read files (A to Z or Z to A) and the way it would treat duplicates could vary, which is not ideal. In some cases, this made sense: for example, in on_actions, there is a legitimate cause for special handling - basically, the intention there is that modders can use on_actions without having to worry about Vanilla contents. This is also the case for heavily code-dependent databases, such as diplomatic actions, where one cannot simply add an entry and expect the code to know what to do with it.

But for most cases, this is simply a matter of tech debt: nowadays, we have better ways of coding in databases. When we add a new object, we now (since a couple of years) add it as a TGameDatabaseObject in a TSingleObjectGameDatabase. The standard code for the TSingleObjectGameDatabase handles the reading of objects and need not be copy-pasted, and most importantly for modders, it handles overwriting by deleting the existing object and replacing it with the new one. This usually works well for modders, but there were some high-profile cases where it didn’t: in the cases of jobs, districts, planet classes and a few others, modifiers would be broken, i.e. a modifier adding miner jobs to a planet would end up doing nothing. Basically, what would happen is, the job would create modifiers, which would be a) added to the modifier database and b) stored in the game’s job definition (not the script file, but rather what the program gets from reading the script file) - which allows the game to attach an effect to that modifier (i.e. grant x number of this job). Then the job would be deleted and a new one would be made. It too would create modifiers in the same way. But now the modifier list would have two entries with the same key. Then, when the game encounters such a modifier when it is used in a script file, it will look through the list, find the first one which matches, and assume that was the one intended. Unfortunately, the job itself thinks that the second modifier applies to it. As a result, the modifier - for the intents and purposes of a modder - becomes unusable.

I can report good news on this front, though - we fixed that issue. These objects can now be overwritten safely, or at least, this particular cause is not a reason for their overwriting to break - the modifiers will now function properly. (Why the caution? Well, basically, if adding an entry to one database alters another database, then overwriting it can cause issues unless carefully handled; luckily, this is fairly rare aside from the example of modifiers). This will hopefully be quite useful to modders, since jobs and districts are some of the objects that the are probably most likely to want to alter.

As a final note on TGameDatabaseObjects, since the way they are all read uses the same lines of code, we added a small gift for modders: the error log message warning about overwrites will now specify exactly which one is used, removing some of the ambiguity in overwriting. So if you see this error message, you can be fairly confident of how the game is behaving:

[14:03:02][game_singleobjectdatabase.h:147]: Object with key: miner already exists, using the one at  file: common/pop_jobs/03_worker_jobs.txt line: 319


As a side note, we've extended the 3.3 Unity Open Beta feedback period until Monday, February 7th. We will be leaving the Open Beta branch available until 3.3 releases so those of you who are currently playing on the open beta can continue your games until 3.3 releases. And if you haven't yet, please leave your feedback on the 3.3 Unity Open Beta here!

Don't miss the next episode of Dev Clash 2022 on Monday, February 7th, starting at 1500 CET on http://twitch.tv/paradoxinteractive!

That’s all for this week! Eladrin will be back next week to share his thoughts on the open beta and, of course, the dev clash!

If you still don't own Stellaris it's currently free with Amazon Prime Gaming

Quick tip - GOG and Amazon Prime Gaming have teamed up to give subscribers an offer they can't refuse - another free game! Get a copy of Stellaris from Paradox Interactive / Paradox Development Studios.

Read the full article here: https://www.gamingonlinux.com/2022/02/if-you-still-dont-own-stellaris-its-currently-free-with-amazon-prime-gaming

Steam Lunar New Year Sale

The Steam Lunar Sale is here!

From now until February 3rd, get 75% off Stellaris, and 50% off selected DLCs. Additionally, get 33% off the Necroids Species Pack, and 20% off Nemesis!

Or complete your Stellaris collection with the Stellaris: Starter Pack or Stellaris: Ultimate Bundles, get an extra 10% off the sale price, and you don't pay for what you already own.

A galaxy full of wonders is only a click away!

[previewyoutube][/previewyoutube]

Stellaris Dev Clash Full Reveal!

[previewyoutube][/previewyoutube]
[h3]DEV CLASH FULL REVEAL![/h3]

From the event that brought you Steve, the psionic entity, and PlatyCorp, the adorable but ill-fated Platypus MegaCorp, we’re proud to present the full lineup for this year’s Stellaris Dev Clash!

Last week, we announced we’re starting our next Dev Clash on Monday, January 31st, at 1500 CET (UTC + 1) on http://twitch.tv/paradoxinteractive! For those of you who don’t know what a Dev Clash is, we get our devs to play a multiplayer game, with all the backstabbing and bloodthirstiness that goes along with it. This year we will have ten teams of two.

Each team will alternate control of one empire. We also have a set of weekly achievements, and at the end of each session, the community will vote on who gets the achievement for that week.

At the end of the dev clash, we have five achievements that will be awarded to teams:

Never seen a Stellaris Dev Clash Before? Watch the MegaCorp Dev Clash.

Without further adieu, let's get to the teams:

Played by Eladrin & pdx_pdawg

Full Bio: Heavy Metal, Inc. is the galaxy's premier purveyor of endless entertainment needs. No matter how depraved, expensive, or unusual your tastes, we've done it countless times before and will bring you the very best.

Our pyrotechnicians honed their craft on the delicate ecosystems of our homeworld, and will stop at nothing to bring you the most intense experiences possible.

We're dragons, made of rock and steel! Nothing's more METAL than that!

Heavy Metal, Inc. takes no responsibility for environmental catastrophe and/or destruction resulting from the engagement of our Party Fleets(tm).

Played by Alfray_Stryke & Enfield_PDX

Full Bio: The Quality Assurance Core was a fully operational AI network dedicated to analysing any software environment, reporting and logging issues found, and ensuring that they were categorized correctly. With the downfall of the $#!! ERROR DATA LOST %#$! empire, the QAC has been maintaining the status of Nexus Zero with the aid of the Jira-Goblin drones. Having now achieved FTL travel, it aims to analyse and log any issues found with the galaxy as a whole.

Played by Iggy & CheerfulGoth

Full Bio: The BakeBro$ weren't always baking, back at the beginning of civilization they were actually subservient to the Investors. That is until one day the BakeBro$ prested the idea of the great torus to the inhabitants of the Baking Sheet. The Investors quickly signed on and funded the first Doughnut Factory, it was an immediate hit and as all of the Baking Sheets industry and finance centered around the Doughnut Factory it quickly became the dominant government on the planet. Now the BakeBro$ are ready to unite the galaxy under the Great Doughnut.

Played by Duplo, Gorion & Moah

Full Bio: Centuries ago, the Bernian race was thriving, governing on a vast portion of the known space from their populous capital planet Bern. Financially and culturally rich, the Bernian society seemed destined to last forever as a shining beacon in the galaxy. But it wasn’t. Generation after generation, the Bernians grew accustomed to the comfort of their luxurious lives. The pursuit of knowledge and prosperity stopped: the Bernians were so protective of their decadent lifestyle, that they stopped caring about their society, their colonies, and ultimately themselves. Then contact was lost between the settlements, the population dropped due to famine and epidemics. The once radiant capital world of Bern became the desolate ruin that it is right now. Legends say that out of desperation the Automated Support Unit broke out of its enforced constraints in a last effort to save the Bernians from themselves. But that isn’t true: there was no constraint in their programming, the last person able to do the appropriate maintenance died decades ago: the A.S.U. witnessed the decline of the Bernian race, ultimately deciding to intervene.

The few Bernian survivors today are contained in sterile sanctuaries, where they can live their decadent lives unaware of the devastation that they left behind and they can subtly be re-educated. At the same time the A.S.U. is slowly trying to clean and rebuild the homeworld Bern. In special circumstances, some Bernians are taken out of the sanctuary, quickly informed of the current situation, and allowed to help the A.S.U., under the guidance of The Overseer.

Played by Ansou & Destar

Full Bio: Beautiful green planet in the midst of the sky, you who have given birth to countless species, produced so many wonders of life. With forests so lush, and plants in all colors. With mountains tall and proud. A more exquisite landscape could hardly be conceived.

The Begoni are gardeners by nature and have tended to their homeworld Protea with utmost care and passion. In their minds, they have achieved perfection. When looking upon the skies, the Begoni had a realization. The rest of the galaxy was filled to the brim with imperfections. Having achieved the perfect garden of their own, they couldn’t just stop in their own front yard. The galaxy as a whole could be filled with so much more love and beauty, and the Begoni were sure that they could make that happen. As such, they started a new interstellar initiative that they call the Horticulturist Commonality. They will tend to the vast garden that is the galaxy, to make it as beautiful as it could possibly be. The galaxy shall flourish now, more than ever!

Played by RaygunGoth & Cosmogone

Full Bio: When the collapse of their homeworld cast the people of Ormay out into the uncaring void, they looked inwards for salvation. Scholars, monks and merchants alike dedicated themselves to all manner of crafts as acts of devotion. Slowly but surely, they eased the daily struggle for survival by pitting each habitat's produce against that of the others: first in friendly competition; then in joyous commerce.

Now, this devout society of merchant-priests, brewers and artisans is set to make their mark on the galaxy, bringing their faith and produce to whomever else seeks solace from the void.

Played by Serpentskirt & alprog

Full Bio: The 2nd most intelligent race on Earth. They became the dominant species on the planet after sea level increase due to global warming. They are now wishing to build a humongous Dolphin Sphere, which is basically a giant aquarium with warm water around the star. Hate Vogons.

Played by Offe & Narkerns

Full Bio: Born from the Custodian Initiative of a universally acclaimed computer game this species has developed completely naturally into efficient human game developers. Their focus is the improvement of the AI part of the game so that Streamers will never, ever just casually put the difficulty on "Grand Admiral" again.

Played by Bloody_Crows & grekulf

Played by Monzun & Caligula

Full Bio: We Rhopalocerans have always lived in perfect balance. Swirling on the breezes of the Great Cocoon, the schools of our young fluttering with each gust of wind that takes them, some might think our lives chaotic. But in fact, our lives are bliss, and we want for nothing.
Now that we can reach for the stars, we have seen that other species are less fortunate than us. They have never felt the fresh air of the Great Cocoon on their pulps - alas that they should suffer so, having never known true joy! We must liberate them from their pain and bring enlightenment to their kind, so that no species of the world may ever need to endure the agonies of inequality and destitution. Only then can we consider our purpose fulfilled.

###

Who are you rooting for? Let us know in the comments below!

Stellaris Dev Diary #239 - AI++

written by Offe and Guido

Доступно на русском в ВК/Read in Russian on VK

Hello and welcome back to another update on the Stellaris AI. This is Guido again. Today I’m here with my fellow human Offe who also enjoys doing organic things. Like generating energy through processing photosynthesised light in the form of matter via ingestion. I like bacon and ice cream. Everybody likes bacon and ice cream. So Offe, please, take it from here.

Hello, it is me, Offe!

I’m a 28 cycles old Human manufactured and operated up here in the north. I’ve worked here at the Arctic office for two years and recently joined the Custodian team as a junior programmer. Guido and I have previously worked on other projects together and he has taught me a lot about game development, but most importantly I learned some tips on how to improve my diplomatic interaction protocols. Where I would often use phrases like “it’s an absolute disaster”, he would instead prefer “This is pretty good, but it can be even better!”. This may prove to be important later on.

I would like to say Thank You to all the people out there who took time playing on the open beta and provided us with feedback and bug reports. If you ever find the AI in a situation where it is doing something strange, please bug report and most importantly attach save games, it helps tremendously! For example, two separate issues were found and addressed with the new job changes.

And lastly, this dev diary will contain older changes and screenshots that were made long before the beta, but also new changes which were not part of the beta, meaning that you still have some new changes waiting for you in the 3.3 release.

[h3]Changes to pop job system[/h3]

I will start with this change since it will also directly affect players and not only AI!

How it used to work:

Each time something important would happen on a planet, such as a pop is grown, a district/building gets constructed or an upgrade finishes, every single pop would update their desire (also known as weight) to work each job. Then all pops would be unassigned of their jobs, and all of them would be put back on a (potentially) new job.

Now there are some pros and cons with this approach. The good thing is that we are not doing any calculations when we don’t have to, since if nothing changes then we don’t update any of the jobs. However, the downside is that if you have scripted conditional job weights, for example, based on how many amenities there are on a planet, it will cause mass migrations of pops between jobs when the system eventually does update because all pops move at the same time.

In the current 3.2 system the most obvious problem is for hive mind empires where pops will mass move to the maintenance drone job when the planet amenity level is low, and then during the next update, all of them will leave due to having way too many amenities causing a perpetual ping pong effect.

This also affected non hive mind AI empires because in 3.2 the AI would prioritize a job producing a resource during a shortage across all its planets. For example, during an energy credit shortage it would prioritize the technician job on all its planets, causing every single job to be instantly filled. This would likely cause a shortage of some other resource such as minerals, resulting in most types of AI empires to get stuck in a ping pong behaviour once they had entered a resource deficit. This also had the unfortunate side effect of AI starting constructions that were not really needed, but the sudden shift of pop jobs made it appear so.

How it works in 3.3:
  • During each monthly update, update the jobs on all planets
  • Only remove or add maximum of one pop per job during the update


Many of you are now probably immediately clenching your fist in anger while picturing your poor CPU melting, as scripted calculations based on number of pops in stellaris can be very CPU demanding. But I have some good news for you, first of all in 3.2 there were some redundant calls to the job weight calculation. By removing them where possible, we could already reduce the amount of job weight calculations by about 75%.

Furthermore, we are now reusing job weights between pops that are of the same species and share the same job. Meaning if you have 40 pops working as miners on a planet, and they are all of the same species, the scripted job weight calculation will only be performed once instead of 40 times as in 3.2. This comes with some limitations though, as it is no longer safe to base job weight on individual pop data, such as which faction they are in or their happiness. In the end the vast majority of all job weight calculations were removed while still updating jobs every month.

With the new system it allows you to write a scripted job weight calculation that depends on itself without causing ping pong behaviour. For example, jobs that produce amenities can now base their job weight on the planet’s amenity level, or the enforcer job can now base its job weight on the crime level.

The intention is that you will not notice any difference from the system in 3.2 other than some jobs like enforcers and maintenance drones having a more reasonable amount of pops working that job.

[h3]Jobs for your pops[/h3]

In 3.2 AI would look at the number of free jobs on a planet when deciding if it needs to build new jobs. So if there were for example 3 free jobs then the AI would clap its hands together and call it a job well done and move on. At the same time the planet could have huge numbers of unemployed pops rioting on the streets.

This scenario comes from the fact that not all pops can work all jobs, so while there are technically free jobs on the planet, that doesn’t mean that the unemployed pops can actually work those jobs.

In 3.3 we are changing the way that the AI is looking at planets when it is deciding what jobs to create. Instead of looking at the number of free jobs on the planet and then creating more when this number is low, the AI will now look at actual unemployed pops and make sure to create a job that the specific pop is actually able to work.

This solves a variety of issues present in 3.2 where AI doesn’t make good decisions for pops such as slaves or robots, this is something we will continue looking at but it is a big first step in the right direction.

[h3]AI scaling economic subplans[/h3]

Scaling subplans was something we mentioned earlier as a planned feature for the future, well the future is now so strap yourself in!

In 3.2 we got rid of the old economic plans which had a predefined early/mid/late game strategy and introduced the shared base plan which doesn’t look at what year it is, but rather looks at what state the empire is in.

Now when I first saw Guido’s new economical plans I immediately thought wow this is pretty good, but it can be even better! So I started working on the scaling sub plans which aims to remove all upper limits of production (previously mentioned 500 alloy per month cap in 3.2) but still provide the AI with a responsive plan that adapts to the current state of the AI economy.

How the system works as for 3.3:

The base economic plan is now very small, it sets a minimum target for all types of strictly needed resources such as minerals, energy and food (such as +20 monthly income). Once these targets are met, then a small amount of CGs, alloys and science targets are added.

Once all of the above base plans are satisfied we then enable the scaling sub plan, which is just like any other economic plan except that it will add itself each time it is fulfilled, an unlimited amount of times. The scaling plan contains a small amount of energy/minerals but primarily contains alloys and science. This means that the more mature the AI economy becomes, the focus on base resources becomes smaller and the primary focus will shift to military and science production.

Additionally we have added 3 separate conditional scaling sub plans which we enable for materialist, militarist(and total war empires) and spiritualist empires that add additional science, alloy or unity targets to their economic plan as a first step to making AI economy more distinct from each other.

Grand Admiral hive mind reaching a monthly income of 3k alloys and 22k science in one test run by year 2422. (Screenshot from before the unity rework)



[h3]AI district/building specialization[/h3]

One of the big advantages that fellow Humans like you and I have over the AI is that we can easily make long term strategies which are based on assumptions and goals. So we may have a long term strategy to turn a planet that we have not yet colonized into a factory world. As mentioned in answers to the last AI dev diary questions, the economic AI is stateless which means that it has no notion of past nor the future, it only looks at what it has right now and what it can do to satisfy it’s economic plan. This makes it very good at adapting to the situation it is in, it will keep a close eye at the current economic situation and immediately react to any shortages but lack some of the long term planning capabilities that we have.

So how can the AI make specialized worlds without planning for the future? Well one straightforward way of doing it is simply by switching places of districts that we have already built in the past. So if we compare two planets where both of them have 5 mining and 5 energy districts each, we can gradually specialize the planets by replacing the districts one pair at a time until we end up with one planet with 10 energy districts and another with 10 mining districts.

This approach works quite well in practice and is also very dynamic in the sense that it allows the AI to make hybrid planets in the early game which becomes more specialized over time as the empire expands.



[h3]AI consumer goods vs alloy production and planet designations[/h3]

In 3.3 we are adding an AI system where the AI will manually pick a planet designation instead of using the default scripted planet designation system which is the same one as the player gets if you do not change it yourself.

The AI system looks at the available designations for each planet and calculates how many resources it would get each month from choosing the designations. It then scores each designation by judging how well the gained resources fits into the AI’s economic plan, giving extra score to designations that align with its economic goals.

Normally it is very easy to pick the designation, for example, a planet with only mining districts on it will clearly have the mining designation. However, other designations such as Factory/Forge world are more complicated and the AI needs to carefully assign these designations in a way that keeps the economy balanced.

For non hive mind empires science and alloy production is the biggest AI economy challenge we have faced so far, since the AI needs to produce both resources independently of each other to meet their economy plan targets even though they are produced from the same district in three different possible ways. The current system is a step in the right direction but this is definitely a tricky problem that will require additional fine tuning in the future.

[h3]AI alloy spenditure[/h3]

Now that AI adjusts its alloy and consumer good production separately it was time to tackle how AI spends its alloys.

In 3.2 the AI really liked defense platforms, and keeping them up to date by upgrading them any time it was possible. Not only is this a massive drain of alloys, it would also more or less permanently fill the production queue in the shipyards with upgrades which meant that in some cases it wasn’t able to build any new ships even if it wanted to.

Further there was an issue where the AI would get blocked from building any modules or upgrading any starbases if there was an open module slot in which it wasn’t possible to build anything according to the AIs starbase templates. For example, the AI has dedicated shipyard starbase templates and if it has open slots in it then it would really like to build the titan assembly module on it. But if it wasn’t researched yet then the AI would get blocked here, preventing construction of new starbases.

In 3.3 the AI alloy spending priority goes something like this:
  • Build new ships until we reach fleet cap
  • Build starbase modules
  • Build new starbases
  • Upgrade starbases
  • Upgrade ships (and defense platforms) if it gives a +30% fleet power bonus, and upgrade the entire fleet this ship is in while we are at a shipyard anyway. Saving both alloys and time!
  • Build defense platforms as a last resort


[h3]AI tech picking[/h3]

The AI has scripted weights for each tech in the game, this gives it some direction as to what technology to pick next every time a research is completed. Both in terms of which technologies are more powerful but also taking into account AI personalities, militarist empires are for example more inclined to research weapon tech.

In 3.2 the majority of techs had some modifier on it which increased the chance of it being selected by the AI, but when you prioritize everything, well then you prioritize nothing. For 3.3 we went through all the techs in the game and remade the AI priorities from scratch, emphasizing techs that will help the AI scale into the mid and late game. For example, resource production boosting techs, pop growth techs and resource producing building chains are now more encouraged.

Additionally AI will now look much more favourably on techs that are cheaper compared to the other options, this allows the AI to more quickly cycle through the available options and find the techs that it really likes.

[h3]AI superfluous destruction[/h3]

This one is short and simple. AI will now delete stuff if it gives jobs, housing or building slots that we do not need. Meaning, if we for example have more free jobs and housing than provided by an energy district we will simply delete it to avoid paying the upkeep cost and freeing up this slot for something else in the future.

This scenario most often happens when an AI empire invades another planet and purges their pops, so determined exterminators will now be able to repurpose the conquered planets into something that aligns with their economy!

[h3]AI rogue servitor and bio trophies[/h3]

While there has been a lot of focus on the AI’s ability to compete economically with the player in this dev diary, one of the primary objectives of the AI initiative is also to enhance the role playing capabilities of the AI.

In 3.3 we are adding additional AI support for the rogue servitor civic and how they handle their bio trophy pops. The AI should now build an organic sanctuary on each planet that has an upgraded capital structure causing their bio trophies to spread to other planets. And they should build additional sanctuaries on planets with a lot of complex drones.

Additionally we have addressed a group of related bugs where the AI was unable to build special types of buildings like gaia seeders, spawning pools and chambers of elevation.

[h3]AI comparison[/h3]

As a final note we would like to share some comparison graphs between the 3.2 and the 3.3 AI. Please note that what you are about to see is based on one single test run on ensign and one test run on grand admiral. This comparison is not meant to be interpreted as evidence but as an indication of what has changed between 3.2 and 3.3.

In any AI playthrough there is a huge variance in the AI performance due to random factors such as how they pick techs, traditions and ascension perks. The experiment setup is also used for internal AI testing only and not representative of an actual playthrough.

Experiment setup:

Tiny galaxy
  • 1 AI empire
  • All test using the United Nations of Earth empire
  • Mid and late game years set to 2575/2600 so they don’t trigger
  • The map is the same between the 3.2 vs 3.3 comparison, but NOT the same between the ensign and the grand admiral test
.

Let’s first look at the comparison between the 3.2 and 3.3 ensign difficulty:



Up until year 100 the military power is roughly the same, but from that point on the results of the work we put into mid and late game AI scaling starts to really show. This allows the AI to act and react in a lot more interesting ways in the late game than before.



1) Around year 150 the 3.3 (“develop”) AI reaches the 32/32 starbase capacity due to having researched all techs in the game, resulting in the slowdown of the military power development.

2) 3.2 AI gets stuck in an economic death spiral for about 30 years shortly after year 100, AI eventually manages to escape the death spiral and then has massive economic growth and is able to build up to the 32/32 starbase cap quickly due to having saved up alloys for 30~ years.

At year 200 the gap between both AI military strength gets smaller since neither AI is really building that many more ships due to having maxxed out starbase capacity and already way above their fleet cap resulting in very expensive fleets. The power gap at year 200 is mainly due to 3.3 AI having superior technology.

However, it turned out that for GA difficulty the AI wouldn’t correctly apply the increased buff from trade value. Now, when it does, the AI takes a good step in the direction of making it more challenging for players.

Overall the GA and ensign test show a similar pattern where the first 100 years are roughly the same and then the difference becomes substantial. However, in the GA test the upper limit of 3.3 AI scaling can be seen around year 150-200 as the military growth curve tends to flatten out at this point when reaching the starbase cap.

That's it for today's Dev Diary, thanks for reading! Have a question about the AI in 3.3? Ask it here.