Stellaris, carnet des développeurs n°172 : Le retour de l'IA (2nd partie : La planification de l'économie).

Qu’est ce qu’une IA qui gère l’économie et où en acheter une? :

Salut à tous les voyageurs de l’espace, ici Zack (ou sidestep). Pendant que The French Paradox était très occupé avec l’IA gérant la partie militaire, je fus très occupé par la partie économique, ce qui est important, aussi important que de savoir que ce sont les crédits qui font tourner les mondes.


Qu’est ce un module économique pour une IA et comment cela fonctionne dans Stellaris? Bon, cela pourrait faire l’objet d’un carnet et ce "module" dépend en plus du jeu duquel on parle. Pour faire court une IA de l’économie décide quand et comment dépenser les ressources. de la même façon, c’est cette dernière qui décide quelles ressources faudra-t-il acquérir. Dans Stellaris plus spécifiquement ce module doit gérer le commerce, les mines spatiales, les modules des stations stellaires, les politiques et édits, les activités prioritaires des populations et bien d’autres choses encore. Mais peut être l’action la plus importante est la gestion des constructions planétaires!

La construction est au cœur de l’économie dans Stellaris. Les bâtiments et quartiers sont à la fois le moteur de l’économie mais aussi un facteur non négligeable dans la croissance de vos populations qui se traduit ensuite par des ressources. Précédemment l’IA gestionnaire construisait de façon indépendante sur chaque planète sans but à long terme en tête. À des intervalles réguliers elle allait de planète en planète et en accord avec un script précis , elle trouvait un bâtiment intéressant à construire, le mettais en file d’attente et passait à la planète suivante et ainsi de suite. Des problèmes fondamentaux existent en construisant de cette façon cependant.

Le Problème :

Tout d’abord un tel système est très lourd à coder et requiert beaucoup de maintenance et d’équilibrage. Si vous changez la façon dont fonctionne à peu près n’importe quoi dans le jeu et que c'est lié à l’économie alors il faudra faire une passe sur l’IA. Ceci peut se traduire par la réécriture de pans entiers du scripts. Prenons un exemple : “Oh si nous changeons ceci alors il faudra plus d’alliage en augmentant le poids des fonderies dans le gestionnaire de construction, mais alors cet autre bâtiment ne sera plus construit en assez grande quantité et donc il faudrait changer ci et ça et… “, bref vous voyez le problème.

Actuellement nous en sommes arrivé à un script à la fois énorme, complexe, pas très explicite et hyper contraint pour chaque bâtiment avec de nombreuses conditions logiques (si/alors) et différents poids. Finalement tout le monde s'y perd un peu. Ci dessous un exemple d’un script pour un simple bâtiment :

Spoiler:
ai_weight = {
weight = 0
modifier = {
weight = 10
OR = {
planet_crime < 15
has_building = building_hall_judgment
}
is_capital = no
free_amenities > 2
owner = {
has_monthly_income = {
resource = minerals
value > 100
}
has_monthly_income = {
resource = alloys
value < 100
}
has_monthly_income = {
resource = alloys
value > 6
}#Check for alloy shutdown
}
}
modifier = {
weight = 200
planet = {
is_capital = yes
NOR = {
has_building = building_foundry_2
has_building = building_foundry_3
}
num_buildings = { type = building_foundry_1 value < 3 }
has_building_construction = no
}
}
modifier = {
weight = 400
OR = {
AND = {
owner = {
OR = {
has_monthly_income = {
resource = consumer_goods
value > 0
}
country_uses_consumer_goods = no
}
}
NOR = {
num_buildings = { type = building_foundry_1 value > 1 }
has_building = building_foundry_2
has_building = building_foundry_3
}
owner = {
has_ai_personality_behaviour = conqueror
OR = {
has_ai_personality_behaviour = opportunist
has_ai_personality_behaviour = purger
has_ai_personality_behaviour = propagator
}
}#Agressive empires but not robot liberators as they tend to be erudite explorers and the like.
}#Give agressive empires 2 alloy factories on planets early on.
NOR = {
has_building = building_foundry_1
has_building = building_foundry_2
has_building = building_foundry_3
}
}
}
modifier = {
factor = 0.5
free_jobs > 3
}
modifier = {
weight = 500
has_building = building_foundry_1
free_building_slots = 0
}#Repairs
}


Comment comparer un poids de 200, 400, ou 500 avec les autres bâtiments contenus dans d’autres fichiers? Aucune idée!

Un second problème est que en fonctionnant ainsi, l’IA est extrêmement réactive mais pas vraiment proactive. Un bas revenu dans une certaine ressources déclenchait une suite d’actions pouvant évaluer la construction d’un bâtiment de façon très favorable et lorsque ce dernier était fait alors le problème était réglé. Mais que se passe-t-il si tout allait bien de base? Comment déterminer ce qu’il faut construire alors? On ajoute alors une nouvelle couche dans le script qui dit quelque chose comme “si tout va bien avec ces ressources alors construisez ceci, mais pas trop quand même parce qu’il faudra des ressources à disposition pour l’entretien, hummm…”. Vous pouvez voir maintenant combien il était difficile de coordonner tout ceci et comment il est facile qu’une suite d’actions entre en conflit avec une autre. C’est aussi un problème parce qu’il faut maintenir et mettre à jour l'ensemble à la main pour chaque script de chaque bâtiment.

Enfin un dernier soucis, le script fonctionne de façon planétaire et il ne prend pas en compte ce qui se construit ailleurs dans le même temps ni pour quelle raison. Ce qui veut dire que si l’IA décide de construire un quartier de centrales sur une planète parce qu’elle manque d’énergie, il y a de forte chance qu’elle fasse de même sur la planète suivante puisque la situation sera inchangée lors de l'évaluation réalisé pour la première planète reste toujours valable pour la seconde. L'IA créant alors un surplus éventuellement inutile. Ceci peut paraître peu important mais répétez maintenant ceci sur 12 planètes et l’économie entière peut alors basculer avec des conséquences massives sur le long terme. L’IA pouvait même détruire certaines réalisations une fois achevés afin de faire de la place pour construire autre chose et ainsi gâcher l’effort précédent.

Il y avait aussi d’autres soucis plus mineurs mais les principaux reste ceux que j'ai mentionné. Parlons maintenant des objectifs de cette refonte :

- Un script moins rigide et plus simple à maintenir;
- Une planification plus proactive;
- Des actions à l’échelle de l’empire et non plus des planètes;
- Une amélioration des performances généralisées;

La Solution, le Plan™ :

La merveilleuse équipe de la qualité a réussi à mettre en forme une liste de conditions économiques qu’un empire pouvait réussir à atteindre à certains points de la partie. Il y a une liste pour le début de jeu et une pour la fin. Lorsque j’ai commencé à retravailler tout ça, je suis arrivé à la conclusion que l’IA avait besoin d’un plan à long terme et que réagir à ce qui arrivait dans le jeu ne suffisait plus. Ceci s’est parfaitement lié avec les mesures de l’équipe qualité et j’ai pensé “Pourquoi ne pas rentrer ces objectifs dans le jeu?”. Ainsi le Plan Économique est né. Ce plan est maintenant au cœur du nouveau système économique et l'IA peut alors se projeter sur le long terme. N’étant que des objectifs, les plans sont entièrement modifiable. Ils peuvent appartenir au début, milieu ou fin de jeu. Je n’ai pas eu beaucoup de temps pour en faire plus mais je suis certain que les moddeurs s'empareront du sujet et que nous en ajouterons à l’avenir. Les plans sont aussi munis de déclencheurs et de poids afin que l’IA les choisissent au mieux selon les circonstances. Un plan est remplacé que lorsqu’il est accompli ou lorsqu’il n’est plus valide (par exemple lorsqu’on entre dans une nouvelle ère dans la partie ou si un empire lithoïde à besoin de nourriture pour des populations organiques qui auraient émigrés en son sein).

Spoiler:
early_default_plan = {
type = early

income = {
energy = 50
minerals = 200
food = 50
consumer_goods = 50
alloys = 100
unity = 50

physics_research = 200
society_research = 200
engineering_research = 200

exotic_gases = 1
volatile_motes = 1
rare_crystals = 1
sr_living_metal = 1
sr_zro = 1
sr_dark_matter = 1
}

focus = {
energy = 10
minerals = 30
alloys = 50
food = 10
consumer_goods = 20
}

pops = 500
empire_size = 1.25

potential = {
country_uses_consumer_goods = yes
country_uses_food = yes
}

ai_weight = {
weight = 1
}
}


Ci dessus vous pouvez voir le plan par défaut utilisé par l’IA au début du jeu. Comme vous pouvez le voir une condition s’applique pour être sûr que ce plan n’est pas utilisé par des consciences collectives puisque cela forcerait l’IA à faire des biens de consommations qu’elles ne pourraient utiliser. Ces contraintes sont aussi utilisées pour tout ce qui à attrait à la destruction de certains bâtiments et quartiers afin de faire de la place pour en construire des nouveaux plus adaptés à la situation.

Ci dessous, je vous joins quelques explication pour chaque élément de script si ça vous êtes intéressé par la modification de ces fichiers. Pour les autres point besoin de lire tout ceci.

Spoiler:
‘type = early’
The type field determines during which part of the game this plan is considered valid, this particular one is valid for the early game so it will only be considered until you reach whatever year has been set as the mid-game start year in the game settings.

‘income = {}’
The income field contains the main economic plan goals that the AI will try to reach when having this plan. Here you can script any available strategic resource followed by how much net income the AI needs to have before it considers that resource goal fulfilled. NOTE: If a resource is not scripted here then that means that the AI will not actively try to build anything that produces that resource, it might do that because a certain building produces something else it needs though.

‘focus = {}’
The focus field can be used to set special focus goals ( net income ) for resources that the AI should specifically try to reach before anything else. This field is great to use to ensure that the AI never dips below a certain net income, and that it makes sure to produce certain resources early on even if there is no deficit of said resource. Minerals and alloys are good example of early game focus resources because the AI needs to produce a considerable amount of them to be competitive, just staying above 0 net income is not enough!

‘pops = 500’
The pops field is the goal number of pops that the AI will try to reach. It will not stop producing pops when this number is reached, however pop growth and assembly buildings will be weighted much lower in favor of more resource production when the goal has been reached.

‘empire_size = 1.25’
The empire_size field denotes, in percentage, a threshold under which the AI should try to keep its Empire Sprawl. In this case 1.25 means that the AI should try to keep its early game Empire Sprawl under 125% of capacity, so that it does not incur too many penalties but still can tolerate some.

‘potential = {}’
The potential field is a standard trigger field, scoped to the AI country, where you can script which type of countries are allowed to use this plan. The base plan potentials are just to ensure that different empire types produce only the resources they need, but you could also script things like special economic plans for when you are at war or if you are in a federation etc.

‘ai_weight = {}’
The ai_weight field is a standard weighting field that you can use to script how much the AI wants to use a certain plan. Since there is only one possible plan per country type and era right now all weights are just set to 1, but you could script up lots of different plans and weigh them differently for different empires based on for example personality, ethics or any other AI property.


Le système de plans ne prend pas en compte la difficulté. Par ailleurs il n’existe pas de plan spécifique pour les ascensions ou dans le but de bâtir des mégastructures. Les éthiques ainsi que le marché ne les influencent pas non plus. MAIS il vous serait possible de faire tout ceci en ajoutant des plans supplémentaires conditionnés par des déclencheurs (comme des plans “avancés” pour chaque phase de jeu une fois le plan générique terminé, un plan de “fin de partie” avec des valeurs extrêmes dans l’alliage et les sciences ou encore un plan en cas de crise de fin de partie afin de concentrer les IA sur la production d'alliage afin de se défendre) car toute cette mécanique est modulaire et ne repose aucunement sur des informations fixées à l’avance. Malheureusement il n'est pas encore possible de faire des plans dans le plans en fonction des conditions mais c'est une idée à étudier éventuellement.

Encore une fois le temps a été très limité et je souhaitais travailler la fondation de ce nouveau système afin qu’il fonctionne bien et qu'il soit robuste sur toute la durée d’une partie. J'ai aussi passé quelques temps à corriger certains bugs de comportements anormaux en fin de partie comme la non destruction de stations minières pour y faire des habitats ou le bug des habitats non colonisés par l’IA. En outre nous continuerons à travailler sur le Plan à l’avenir.

L'Exécution du Plan™ :

Comment l’IA traduit-elle donc ces plans en actions? Une très bonne question n’est ce pas. À intervalles réguliers, l’IA regardera sa situation économique (revenus, déficits, budgets, etc) et la comparera au plan actif. Elle en tire alors les actions qu’elle a besoin pour accomplir les objectifs du plan et crée une file de construction à l'échelle de l'empire pour ce faire.


La file peut être vue en jeu lorsque vous passez votre souris sur un emplacement vide ou bloqué avec la commande debugtooltip activée comme sur l’image ci dessus (les chiffres sont les scores attribués par l’IA à chaque bâtiment). L’IA recalculera les scores de temps en temps afin qu’elle puisse s'adapter à de nouveaux événements.

La file de constructions est faite de façon à ce que l’IA ne fait que ce dont elle a besoin (en incluant les revenus des bâtiments à venir) et si les investissements peuvent être fait lorsqu’ils sont réalisés. Ensuite, l'IA teste les différentes combinaisons afin de savoir laquelle est la plus efficace. Ceci prenant en compte le coût d'entretien des bâtiments et les limites technologique de l’empire au moment du calculs (d’ailleurs l’IA ne se donne pas d’objectifs technologiques en complément des objectifs économiques mais c’est une idée à creuser). L’un des bénéfice de ce système est que vous n’avez plus à spécifiquement écrire des lignes de codes pour que l’IA puisse construire certains bâtiments. Ceci veut aussi dire qu’il est maintenant plus rapide d’ajouter, dans les mods, de nouveaux bâtiments qui produisent des ressources différentes car l’IA s’en occupe (si ces ressources sont présentes et nécessaires dans le plan).

La gestion se fait aussi de façon globale et non plus planétaire. Ainsi l’IA conserve la trace de ce qu’elle construit et évite de dépasser ces objectifs (NdT : comme une production de nourriture peu utile en grande quantité sauf cas spécifique). Les modificateurs planétaires seront mieux pris en compte et ainsi l’IA devrait tendre vers plus de spécialisation (ce ne sera pas non plus l'hyper spécialisation comme peut le faire un joueur). Elle ne construira pas plus de bâtiment sur des planètes déjà en manque de main d’oeuvre. En outre l’IA regardera tout autant les ressources productives que les"ressources" de support comme les logements, les services ou n’importe quelle autre ressource nécessaire. Cependant si cette dernière n’est pas la priorité, il se peut qu’elle vive avec quelques déficits pendant un temps. Des priorités s'appliquent aussi pour la croissance de la population via des multiplicateurs définis pour certains bâtiments et un objectifs de populations est donné dans le plan. De la même façon les bâtiments et districts possèdent des déclencheurs afin d’être détruit si besoin. Je n’ai malheureusement pas pu retoucher ce qui a attrait au déclenchement de la terraformation en ville monde (NdT : car il faut parfois détruire des secteurs pour ne faire que des quartiers d'habitations ce qui est assez particulier).

(NdT : petit aparté) En parlant de populations, ces dernières ont aussi un score d’activité permettant au jeu de mettre la meilleure population disponible pour une activité donnée. Grâce à la commande debugtooltips il sera possible de voir ces valeurs :


Sur cette image, on voit que cet artisan aimerait beaucoup être administrateur, mais artisan est l’activité où cette population est la plus utile pour le moment (NdT : surement car il n’y a pas d’autre place pour devenir administrateur). De façon évidente les activités plus basse dans l’échelle sociale ne sont pas digne de considérations pour ce spécialiste.

En faisant en sorte de voir ces informations plus facilement nous avons pu résoudre certains bug comme celui des robots mineurs qui allait remplir en premier des activités différentes de celle de mineurs (NdT : fin de l'aparté).

Comment l’IA arrive donc à mettre des priorités aux différents bâtiments afin de créer la file de construction? Une question judicieuse ! Pour y répondre nous avons besoin de comprendre comment l’IA attribue les différents scores à chaque bâtiment et chaque quartier. Les scores prennent plusieurs paramètres en compte : les objectifs du plan, les revenus nécessaires pour le remplir, les revenus et déficits actuels, la production brute des ressources, les ressources en support (services, criminalité, logement, etc) et enfin si cela contribue à l’augmentation de la population. Un bâtiment donné aura un score en fonction de chacun de ces paramètres, score alors pondéré par différents multiplicateurs (combien nous manque-t-il de cette ressources? De combien ce bâtiment améliorera la situation?) eux aussi multiplié par des multiplicateurs prédéfinis. Ensuite une bonification est ajouté si la ressources produite compense un déficit ou nous rapproche un peu plus du but. Remarquez que le système prend aussi en compte les bâtiments qui sont déjà dans la file de construction. Ainsi si quatre quartiers miniers sont déjà présent et que ces derniers règleront les problèmes de minerais, alors le cinquième quartier de minerais dans la queue ne profite pas du bonus de déficit!

Spoiler:
AI_DEFICIT_SCORE_MULT = 50 # AI will score buildings producing resources in deficit this much more
AI_FOCUS_SCORE_MULT = 10 # AI will score buildings producing focus resources this much more
AI_AMENITIES_SCORE_MULT = 2 # AI will score amenity buildings this much more than other misc resources
AI_HOUSING_SCORE_MULT = 5 # AI will score housing buildings this much more than other misc resources
AI_CRIME_REDUCTION_SCORE_MULT = 2 # AI will score crime fighting buildings this much more than other misc resource
AI_ADMIN_CAP_SCORE_MULT = 2 # AI will score admin cap buildings this much more than other misc resource
AI_POPS_SCORE_MULT = 5 # AI will score pop growth and assembly buildings this much more ( already fairly high weighted in code )
AI_UPGRADE_SCORE_MULT = 40 # AI will score building upgrades this much more ( since they don't take up a new building slot )


Ci dessus vous pouvez voir comment les multiplicateurs s’appliquent à chacun des paramètre de calcul. Ils sont tous placés dans le fichier “define” et peuvent donc être modifiés.


Tout ceci peut sembler très compliqué et assez mathématique. Voici donc un exemple pour illustrer.

Si les Blorg ont actuellement un revenu convenable dans toutes les ressources sauf pour les minerais où il y a un déficit de 1 et que l’IA assurant la gestion de cette empire utilise un plan lui demandant d’être à 200 de minerais de revenus et qu’elle a un focus de 30 alors l’algorithme pour appliquer le score au quartier minier sera :

Les Blorg ont actuellement un manque de -201 de minerais par rapport à leur but ce qui lui donne un importante valeur de base puisque l’écart relatif est immense. Le quartier minier produisant du minerais et le focus (ou objectif de revenu) demandant d'accroitre cette prodcution, la valeur est multiplié une première fois. Enfin le fait qu’il y a actuellement un déficit de minerais dans l’empire permet de réappliquer un dernier multiplicateur, lui aussi défini.

Cet algorithme attribue donc un score au quartier minier qui va donc s’insérer dans la file de construction (une à plusieurs fois si nécessaire). Ceci fonctionne de façon similaire pour tous les bâtiments, l’idée importante est que le score est lié à la distance qui vous sépare dest objectifs et focus du plan. Ceci veut dire que s’il vous manque qu'un peu de revenu dans une certaine ressource alors le score du bâtiment la produisant ne sera finalement pas très élevé. Enfin si un tel bâtiment est déjà présent dans la file, l’IA ne prendra pas forcement en compte ce dernier puisque l’objectif sera déjà atteint par celui ou ceux déjà dans la file.

Il faut se souvenir que les focus sont supplémentaires aux objectifs du plans. Ils permettent de donner des priorités à l'IA dans ce qu'elle doit produire d'abord avant de se concentrer sur autre chose. L’IA n’atteindra peut être jamais les 50 d’alliages par mois en suivant le plan de début de partie, mais avoir un tel but veut dire qu’elle y appliquera un score plus important et donc qu’elle se concentrera sur la production d’alliage (ce qui est important en début de partie) mais aussi que ce but sera plus lourd que les autres relativement. Si l’IA manque de minerais alors elle mettra l’accent sur les quartiers miniers (ou les mines spatiales) même si les objectifs en alliage ne sont pas atteint.

Puisque les objectifs des plans ne peuvent pas être définis de façon dynamique en fonction de ce qui peut arriver en partie ( exmple un nombre de planète changeant au cours du temps), les objectifs de revenus sont là pour être sûr que l’IA soit positif dans certaines ressources (nourriture, bien de consommations) lorsque c’est nécessaire avant qu’elle n’atteigne la crise économique (et aussi pour créer une réserve tampon en ca sde besoin) . Si nous pouvons les programmer en fonction du nombre des planètes ou de d'autres paramètres variables ça serait super.

Les objectifs des plans sont fait pour des ères de jeu, ce qui se traduit par des dates fixes. Que l’IA n’atteigne jamais ces buts n’est pas le plus important, elle y travaillera tout de même quoi qu’il arrive. Parvenir à les atteindre c’est bien, mais même sans pouvoir y arriver elle les aura toujours pour se guider. Un peu comme les plans à long terme de nos vie, hehe.


L'évaluation du Plan™ :

Ainsi ce nouveau système arrive-t-il à résoudre tous les problèmes précédent? Oui, il le fait .

Il n’y a plus besoin d’écrire des scripts complexes pour chaque bâtiment, à la place il suffit de modifier un plan pour modifier un objectif et d'affecter une importance de cette ressources aux yeux de l’IA. Le plan assure aussi que l’IA soit proactive au lieu de ne faire que réagir aux événements extérieurs pour résoudre des déficits. En outre, l’IA à maintenant une vision globale de ses constructions et arrête de prendre isolément ses planètes. Tout ceci grâce au Plan™.

Cela sonne bien mais la question essentielle demeure : l’IA est-elle meilleure au globale? Eh bien … Oui!

Au cours de nos tests, nous avons pu voir des IAs beaucoup plus robustes et meilleures dans la gestion de leurs économies au globale. Sachez que nous n’avons pas trouvé le temps pour retravaillé la partie du code qui s’occupe des filiales ni celle qui s’occupe des flottes mais grâce à l’amélioration de l’économie en générale, l’IA s’en sort bien mieux dans ce secteur. Enfin et surtout, tout ce qui a pu être produit pour l’IA n’a pas disparu. En effet si l’IA ne trouve plus rien a faire car ayant rempli les objectifs du plan, alors l’ancien script reprendra la main. Ceci veut dire qu’une fois que l’IA ne trouve plus de plan elle revient à une construction de type planétaire, en effet, l’IA ne pouvant pas utiliser de plan avec des valeurs infinis. Une telle amélioration serait très intéressant cependant. Pour le moment je pense que le mieux est encore d’écrire un plan avec des valeurs vraiment très élevées et d’observer l’IA essayer de les atteindre, haha. Vous avez par ailleurs toutes les informations nécessaires pour analyser son comportement maintenant.

Et les secteurs automatisés alors ?
(NdT : question de la communauté)

L’idée de reprendre la mécanique pour l’automatisation des secteurs est une très bonne idée sur le papier. Seulement je pense aussi que l’adapter sera un peu plus difficile que cela. Une autre bonne idée proposé serait de pouvoir piloter l’IA des secteurs avec l’aide de plans mais il reste encore beaucoup de chemin à parcourir à la fois du côté du code mais aussi du côté de l’interface utilisateur pour voir se réaliser une telle mécanique. Merci beaucoup en tout cas pour vos idées et vos retours, ces derniers nous sont très utile d’où le faite que je passe un peu de temps avec vous.

Je suis très heureux de tout ce travail accompli ! Bien sûr, je ne fus pas tout seul et je suis très reconnaissant du service de la qualité et des autres développeurs pour toute l’aide qu’ils ont pu m’apporter. Maintenant alors que l’extension Federations va bientôt sortir j’adorerai voir comment vous vous en sortez et comment vous feriez vous pour modifier tout ceci jusqu’à l’infini .

Je vous remercie de m’avoir lu et vous souhaite bonne chance parmi les étoiles!


Il reste du travail à faire afin d'affiner le dispositif et ce dernier est prévu. N'hésitez pas à jeter un oeil sur le forum pour ne rater aucune nouvelles informations sur l'expension Federation accompagnée de sa mise à jour 2.6 "Verne". Pour rappel cette dernière sort mardi 17 Mars et vous pouvez déjà la précommander sur Gamesplanet avec une réduction en utilisant le code FED5 jusqu'à la fin mars.
Merci à sidestep, MatRobert, Caligula Caesar, Eladrin et Moah pour l’enrichissement de ce carnet avec leurs commentaires et leurs réponses aux questions.