Alt-F4 n°33 - Vanilla : au shaker, pas à la cuillère  30-04-2021

Écrit par Villfuk02, redlabel, édité par stringweasel, Nanogamer7, Conor_, Therenas, Firerazer,
traduit par bev, Firerazer

Sommaire

Dans ce délicieux numéro 33 de Alt-F4, Villfuk02 nous présente son mod le plus récent : “The Recipe Randomizer” ! Un effort particulier est placé pour vous montrer l’ensemble des problèmes qui doivent être surmontés pour créer un générateur de recettes aléatoires qui soit réellement correct. Après cela, redlabel nous annonce un événement de chez COMFY, qui a de fortes chances de tout faire péter.

Vanilla : au shaker, pas à la cuillère Villfuk02

Vill’s Recipe Randomizer fait exactement ce que son nom suggère : il rend les recettes aléatoires. À première vue, cela peut sembler une idée très stupide, mais très simple. Cependant, dès que vous essayez de la rendre moins stupide, elle devient rapidement très compliquée.

Échantillon gratuit de spaghetti
Exemple d’usine fabriquant des packs de science de production à partir de capsules de distraction, de commutateurs d’alimentation électrique et de munitions pour lance-flammes.

Comment cela a commencé

J’ai commencé à travailler sur ce projet en septembre 2020. À l’époque, j’essayais de faire un mod à la fois simple et unique. Il n’était pas censé être jouable, ni même bon, juste quelque chose d’amusant à faire. Après avoir rencontré quelques problèmes, sachant très bien que je faisais un mod que personne ne jouerait de toute façon, j’ai abandonné et je n’ai plus jamais touché à la programmation.

Après deux autres projets ratés, je suis revenu à Factorio, cette fois en tant que joueur. J’ai joué au jeu de base, puis à Industrial Revolution 2, et ensuite j’ai essayé Space Exploration. J’adore jouer avec les mods de révision car cela me permet d’apprendre de nouvelles recettes, de découvrir de nouveaux agencements d’usines et de résoudre de nouveaux problèmes logistiques. Mais la plupart des mods de révision sont très fastidieux et je m’en lasse rapidement. C’est alors que j’ai réalisé qu’un mod aléatoire avait en fait une utilité : c’est comme une réserve illimitée de mods de révision tout en conservant l’aspect classique du jeu ! Le plus gros avantage pour moi est que je n’ai pas à créer de nouvelles machines ou de nouveaux graphismes puisqu’il s’agit uniquement de jouer avec des chiffres et des lettres.

Pas aussi simple qu’il n’y paraît

Le mod pourrait simplement remplacer chaque recette et lui faire prendre des objets aléatoires comme ingrédients. Cela serait assez inutile car, par exemple, la science rouge pourrait demander du combustible nucléaire comme ingrédient, alors que vous ne l’avez pas encore recherché. J’ai donc décidé de le faire se faufiler à travers l’arbre des technologies, et pour chaque recette qui est débloquée, de ne prendre que les objets débloqués avant elle comme ingrédients potentiels. Il y a bien sûr des exceptions dans certains mods, où vous pouvez débloquer une recette avant même de pouvoir la fabriquer, donc je dois être un peu plus prudent.

Vous ne voudriez probablement pas faire un convoyeur souterrain à partir de machines à vapeur et de laboratoires. Ce serait beaucoup trop cher. Je devais trouver un moyen de rendre les recettes plus équilibrées. J’ai donc décidé d’implémenter un algorithme qui calcule la valeur de chaque objet en fonction des ressources nécessaires à sa fabrication. Nous pouvons facilement calculer qu’un circuit électronique nécessite 1 minerai de fer et 1,5 minerai de cuivre :

Comment c’est fait : Circuit électronique
1,5 minerai de cuivre plus 1 minerai de fer font un circuit électronique.

Disons que le minerai de cuivre et le minerai de fer ont tous deux une valeur de 1, ce qui signifie que les circuits électroniques auraient une valeur de 2,5. Le générateur de recettes aléatoires sait maintenant qu’il peut utiliser par exemple un convoyeur (valeur 1,5) et un minerai de cuivre (valeur 1) comme nouvelle recette pour les circuits électroniques. Il y a un certain écart toléré dans la valeur finale. Cela rend les recettes un peu plus uniques, mais surtout, il est plus facile de trouver une combinaison valide, ce qui accélère le processus.

À ce stade, j’ai publié le mod et, d’après les réactions et les tests effectués, il est devenu évident qu’il y avait de nombreux bugs (bien sûr) et deux “gros” problèmes. Le mot gros est entre guillemets car le mod était encore plus jouable que ce que l’on pouvait attendre, même d’un générateur aléatoire. Je voulais cependant que les joueurs puissent l’apprécier, et pas seulement l’expérimenter.

Les premiers problèmes

Le premier problème était le bois. Les réglages par défaut faisaient en sorte que le bois ne soit pas inclus dans le processus, mais de nombreuses recettes utilisaient des poteaux électriques en bois comme ingrédient ! Comme vous pouvez l’imaginer, la solution aurait dû être a été assez simple et ennuyeuse. J’ai ajouté une étiquette pour les ressources non aléatoires, comme le bois, et tout objet qui a strictement besoin d’un objet avec cette étiquette comme ingrédient en obtient une aussi.

Le second problème était que même si les recettes nécessitaient la bonne quantité de ressources, elles étaient souvent trop complexes et semblaient injustes. Le mod ne tenait pas compte du nombre d’étapes de fabrication ni du temps de fabrication. Le pack de science de l’automatisation (rouge) en est un bon exemple. Il est très bon marché, avec une valeur de seulement 3, mais il faut 5 secondes pour le fabriquer. Il était utilisé dans de nombreuses recettes, comme un composant de base, tout comme les engrenages. Son temps de fabrication plutôt long signifie que vous pourriez avoir besoin de beaucoup de machines d’assemblage faisant de la science rouge juste pour quelque chose de tout simple comme des convoyeurs souterrains. Un autre exemple problématique est que des objets simples comme des engrenages pourraient nécessiter de nombreuses étapes, comme les fabriquer à partir de briques de pierre, qui pourraient être fabriquées à partir de bâtons de fer, qui pourraient être fabriqués à partir de tuyaux, etc. J’ai donc fait en sorte que le mod calcule une deuxième valeur, appelée complexité, pour chaque objet. La complexité prend en compte le nombre d’étapes de fabrication nécessaires, la quantité des divers ingrédients (et les résultats) ainsi que le temps de fabrication.

Équilibrer les ressources brutes

Il semblait que j’avais trouvé la méthode de génération aléatoire parfaite, mais là encore, certains problèmes (et bugs) se sont révélés. Souvent, les recettes n’utilisaient qu’une seule ressource (souvent du fer ou de la pierre), ce qui était un peu terne, et vous deviez partir en quête de minerais lointains parce que vous aviez tellement besoin de la ressource choisie. De plus, le pétrole n’était souvent pas nécessaire pour lancer la fusée. Pour une recette donnée, tous les objets valides avaient la même probabilité d’être choisis, de sorte que les objets sans pétrole étaient beaucoup plus nombreux que les quelques produits à base de pétrole. J’ai essayé quelques stratégies pour pousser l’algorithme dans la bonne direction, mais aucune n’a vraiment fonctionné. Je pouvais simplement lui dire d’utiliser plus de plastique ou de carburant solide, mais que faire si vous voulez jouer avec des mods et qu’il y a encore plus d’objets à privilégier ? Je voulais une solution universelle.

Je connaissais déjà une approche qui pouvait résoudre ce problème, mais j’avais peur de la mettre en œuvre parce qu’elle rendrait tout beaucoup plus compliqué. Cela signifie plus de temps de développement, plus de bugs et des temps de chargement potentiellement beaucoup plus longs. Après avoir essayé sans succès de trouver un moyen plus simple d’obtenir un résultat similaire, j’ai finalement décidé d’opter pour cette solution compliquée.

L’idée principale était d’utiliser les quantités de ressources brutes au lieu de la seule valeur totale. Cela signifie que le mod peut s’assurer que chaque recette aléatoire nécessite la bonne quantité de ressources brutes, garantissant ainsi que toutes les ressources brutes sont utilisées. Comme pour la valeur totale, les quantités de ressources brutes pour chaque recette peuvent varier un peu, ou être complètement aléatoires en fonction des réglages du mod. Plutôt simple, non ? Eh bien, maintenant, au lieu de faire des calculs avec un seul nombre, je dois en faire avec plusieurs et la logique est beaucoup plus compliquée. Heureusement, avec quelques optimisations et des tests rigoureux, le mod fonctionne bien et reste assez rapide.

Et c’était toute l’histoire de Vill’s Recipe Randomizer!

Il faut aller plus loin

Sauf que je n’ai pas parlé de certains problèmes IMPORTANTS (remarquez l’absence de guillemets et les majuscules) qui étaient présents dès le début. L’un d’eux est la boucle de recette. L’algorithme peut se bloquer en essayant d’évaluer la valeur de l’une des recettes ou la calculer de manière incorrecte. Les boucles contenues dans une seule recette sont simples à traiter. Pour analyser la recette, l’algorithme élimine les objets qui apparaissent à la fois comme ingrédient et comme résultat, ce qui supprime la boucle. Il peut ensuite rajouter les objets supprimés, car leurs valeurs sont maintenant connues, ce qui rend la recette compatible avec le processus aléatoire. Dans le cas du jeu de base, cela s’applique au procédé d’enrichissement Kovarex et à la liquéfaction du charbon :

Nettoyez-moi ça !
40 U-235 et 2 U-238 peuvent être enlevés du Kovarex et 25 huiles lourdes peuvent être enlevées de la liquéfaction du charbon.

Les boucles avec plus d’une recette sont quelque peu problématiques. Dans la version classique, il n’y a pas de boucles avec plus d’une recette (à l’exception de la mise en baril et de la vidange, qui n’est pas aléatoire par défaut de toute façon), il est donc assez facile de les oublier. Mais avec les mods, elles sont partout ! Le générateur de recettes aléatoires peut également créer accidentellement une boucle dans certaines conditions. Pour illustrer le problème, nous avons besoin d’un exemple. Prenons l’exemple des saphirs synthétiques dans Industrial Revolution 2. Pour fabriquer un saphir, il faut un minerai de nickel pur, de la silice et de la poussière de saphir, mais la poussière de saphir est fabriquée en broyant des saphirs, ce qui crée une boucle :

La boucle du saphir

La façon dont j’ai résolu ce problème est que lorsqu’une boucle est détectée, elle est coupée en un point et les recettes sont ensuite fusionnées en une seule. La nouvelle recette est alors utilisée pour le calcul au lieu de celle avec laquelle la boucle coupée s’est terminée. Ici, on fusionne les deux recettes en enlevant les trois poussières de saphir au milieu, puis on peut enlever les deux saphirs qui sont à la fois un ingrédient et un résultat :

Saphir non bouclé

Nous nous retrouvons avec une recette pour fabriquer des saphirs en laissant de côté les détails problématiques ! Mais que se passe-t-il lorsqu’il y a des boucles qui se ramifient ou des boucles dans des boucles ?

Diagramme en boucle
Ceci n’est pas basé sur une recette spécifique, mais je suis sûr que quelque chose d’au moins aussi compliqué que ce diagramme existe dans un mod quelconque.

Disons simplement que les choses tournent mal. Je pense avoir résolu le problème dans le mod, mais je ne vais pas entrer dans les détails ici, ce n’est pas un cours de théorie des graphes, et je ne suis même pas sûr que la solution fonctionne de manière fiable.

Mon ennemi juré

Et maintenant, le plus gros des problèmes : les recettes à sorties multiples. Prenons l’exemple du traitement avancé du pétrole.

Traitement avancé du pétrole

Par défaut, le pétrole brut a une valeur de 0,4 (nous ignorons l’eau pour l’instant). Cela signifie que la recette a une valeur totale de 40. Nous savons donc que 25 pétrole lourd + 45 pétrole léger + 55 gaz de pétrole devraient avoir une valeur totale de 40, mais quelle proportion de cette valeur est associée à chacun des produits ? Il existe de nombreuses façons d’aborder cette question, qui m’a pris beaucoup de temps et causé de nombreux maux de tête. Passons en revue les deux options les plus différentes.

Le plus simple : il suffit que la valeur de chacun des résultats soit une partie égale de la valeur totale. Cette solution est généralement raisonnable, mais elle s’effondre lorsqu’on introduit des déchets. Par exemple, le processus d’enrichissement Kovarex produit 41 U-235 et 2 U-238, l’algorithme supposerait qu’ils ont tous deux la même valeur, mais vous savez probablement que l’U-235 a beaucoup plus de valeur. Cette approche n’est donc pas vraiment utilisable.

Le “meilleur” : il suffit de faire en sorte que chaque partie ait la pleine valeur, mais gardez une trace des sous-produits que vous pourrez soustraire plus tard. Par exemple, dans le traitement avancé du pétrole, le pétrole lourd a comme sous-produits le pétrole léger et le gaz de pétrole. Cela signifie que le lubrifiant les a également comme sous-produits, car il est fabriqué uniquement à partir de pétrole lourd. Si nous voulons fabriquer un répartiteur express, nous avons besoin, parmi d’autres ingrédients, de lubrifiant et de circuits avancés. Les circuits avancés ont besoin de pétrole, mais nous en avons un peu comme sous-produit du lubrifiant, donc nous pouvons le soustraire. Le seul sous-produit qui reste est le pétrole léger. Que faisons-nous avec le pétrole léger ? Nous pouvons bien sûr le craquer pour économiser encore plus de pétrole. Mais cela nécessite de l’eau. Est-il plus économique d’utiliser plus d’eau ou plus de pétrole ? Eh bien, calculons les deux options au cas où.

Comme vous pouvez le constater, cette approche est incroyablement compliquée. Il y a beaucoup de cas limites et de questions auxquelles il faut répondre. Par exemple, que faire des sous-produits excédentaires lorsque les ingrédients d’une autre recette n’en veulent pas ? J’ai essayé de mettre en œuvre une version de cette approche et je dois dire que j’ai plutôt bien réussi. Cela ne m’a pris qu’une centaine d’heures et j’ai dû corriger environ un million de bugs. Et quelle a été la récompense ? Eh bien, cette solution n’est pas encore parfaite, même si elle s’en rapproche beaucoup. Je ne parvenais plus non plus à donner un sens à mon propre code. Tout se cassait à chaque fois que j’essayais d’ajuster quelque chose. Et surtout, le chargement du mod avec le jeu Factorio de base prenait entre 10 secondes et 10 minutes. Puisque je veux que le mod soit compatible avec le plus grand nombre possible d’autres mods (et qu’il fonctionne avec le Factorio classique, ce serait bien aussi), j’ai décidé que ce n’était pas la bonne solution.

Enfin, après une réflexion plus approfondie, je suis arrivé à l’algorithme que j’utilise maintenant. Il s’agit essentiellement d’un compromis entre les deux approches décrites ci-dessus. Il fonctionne assez bien et est assez simple. Mais il n’est pas assez simple pour que je puisse l’expliquer, car il faudrait que je parle des nombreuses autres bizarreries de l’algorithme d’évaluation. Il n’évalue pas toujours très bien toutes les recettes à sorties multiples, mais il ne se plante pas non plus dans les cas limites (je l’espère).

Dernières réflexions

Voilà qui conclut notre tour d’horizon des rouages internes du Recipe Randomizer. Si vous avez des questions ou des suggestions, vous pouvez m’envoyer un message sur mon serveur Discord. En parlant de ça, j’aimerais remercier toutes les personnes qui l’ont rejoint et qui ont partagé des bugs, des idées, qui ont testé des choses ou qui m’ont soutenu pendant le développement. Le mod n’aurait pas été aussi loin sans vous !

Démineur COMFY ! redlabel

Pour célébrer un nouveau design de carte par le légendaire cartographe mewmew et un tout nouveau Ryzen 9 5950X équipé par Gerkiz, COMFY Factorio organise un événement spécial le 1er mai à 17 heures UTC. Chacun et sa famille sont invités, pas besoin de RSVP.

Démineur dans Factorio

Si quelqu’un se demande de quoi il s’agit, il s’agit d’une nouvelle carte où l’expansion de la base se fait en résolvant un casse-tête Démineur. Pour désactiver une mine, il faut placer un four sur celle-ci. Si vous le placez sur un endroit dégagé, vous déclencherez une explosion, et si vous marchez dessus sans l’avoir détectée au préalable, vous obtiendrez le même résultat. Les erreurs coûtent cher, car elles libèrent des déchiqueteurs maléfiques et provoquent des explosions nucléaires. Les joueurs peuvent également gagner (ou perdre) des points en fonction de leurs performances, et se comparer aux autres grâce à un tableau de bord qui garde la trace des précieux points Internet.

COMFY est l’une des principales communautés multijoueurs de Factorio et certaines de nos créations sont Mountain Fortress, Biter Battles, Fish Defense, Chronotrain et Cave Miner. Et très, très bientôt, il y aura une carte avec des pirates et des voiliers ! Restez à l’écoute pour celle-ci.

Vous pouvez rejoindre la communauté COMFY qui compte près de 3500 membres sur notre Discord.

Le compte à rebours est terminé

Contribuer

Comme toujours, nous attendons vos contributions pour les Alt-F4, que cela soit par la soumission d’un article ou en aidant pour les traductions. Si vous avez quelque chose d’intéressant en tête que vous souhaitez partager avec la communauté, vous êtes au bon endroit. Si vous n’êtes pas sûr, nous serons heureux de vous aider en discutant structure, contenu et idées. Donc si vous voulez vous impliquer dans les Alt-F4, rejoignez-le Discord pour ne rien rater !