Alt-F4 #37 – Kombinator Crash-Kurs Teil 2  28.05.2021

Geschrieben von pocarski, editiert von stringweasel, Nanogamer7, Conor_, Therenas, Firerazer,
übersetzt von EDLEXUS, lektoriert von dexteritas

Inhaltsverzeichnis

In der 37sten Woche, in der eine neue Ausgabe ALT-F4 erscheint, präsentieren wir: Ausgabe 37! Was für eine Überraschung! In dieser Ausgabe ist unser aktiver Autor pocarski zurück, mit neuen einsteigerfreundlichen Erklärungen und Beispielen, wie du deine Fabrik mit einigen Kombinatoren und Schaltungen aufpeppen kannst.

Kombinatoren 2: Erweiterte Logistik pocarski

Vor einigen Wochen schrieb ich einen Artikel über die Verwendung von Kombinatoren zur Verbesserung spezifischer Bauten. Dieses Mal werden wir uns mit generellen Anwendungen befassen, um die gesamte Fabrik effizienter zu gestalten. Wir werden uns Stolperfallen in typischen Designs anschauen, uns überlegen, wie wir diese Probleme lösen können und dann diese Lösungen mit dem Schaltungsnetz implementieren. Diese Verbesserungen können sowohl mit Robotern, als auch mit Zügen vorgenommen werden und sind so einfach, dass sie fast keine Kombinatoren benötigen. Lasst uns also gleich anfangen!

Roboter: Netzwerk-zu-Netzwerk-Interface

Wir kennen alle dieses Problem: Man schafft mehr Bedarf für Roboter, und alle Roboter vom anderen Ende der Fabrik beschließen plötzlich, dass es eine gute Idee wäre, tausende Kacheln zu reisen, am besten durch Gebiete ohne Roboterhangars. Im besten Fall führt das zu etwas Frustration über die Ähnlichkeit mit Lieferdiensten aus dem echten Leben, während im schlimmsten Falle die Roboter von Beißern zerstört werden oder auf der Hälfte des Weges umdrehen, um an dem gerade verlassenen Roboterhangar zu laden, was keinen echten Durchsatz am Ende schafft. Das passiert, wenn das Netzwerk eine Innenkurve besitzt, was zu einer großen Fläche ohne Logistiknetz führt, welche dann von dummen, der Luftlinie folgenden Robotern genutzt wird, um stecken zu bleiben.

Ein Großteil der Roboter einen Netzwerkes, gefangen in der Batteriereichweite.
Diese Roboter haben nicht genug Akku, um die Lücke zu überqueren und drehen deshalb immer auf halber Strecke um.

Um das zu vermeiden wurde eine Regel aufgestellt: “Du sollst keine Logistiknetzwerke mit Konkaven konstruieren!”. Klingt einfach, oder? Die Basis nimmt einfach die Form einen riesigen Rechteckes an, und so werden keine Ecken geschnitten. Das ist eine mögliche Lösung, aber das schränkt dich in deinen Expansionsmöglichkeiten massiv ein, da das Logistiknetz immer in Rechteckform erweitert werden muss. Das führt zu Situationen, wo die tatsächliche Basis nur einen kleinen Teil des vom Logistiknetz abgedeckten Bereich einnimmt.

Eine Basis mit einem störenden “Stamm”, der die nötige Logistiknetzabdeckung massiv vergrößert.
Um das Logistiknetzwerk so zu erweitern, das der "Stamm" mit eingeschlossen wird, ist die Bekämpfung einer Menge Beißer nötig.

Ein viel besserer Weg, dieses Problem anzugehen ist es, die Netzwerke aufzuteilen. Im Prinzip konstruiert man statt einem großen Rechteck viele kleine rechteckige Logistiknetzwerke, die untereinander nicht verbunden sind und durch ihre Anordnung beliebige Formen abdecken können. Da jedes der einzelnen Netzwerke immer noch konvex ist, werden die Roboter nie das Netzwerk verlassen. Aber wie werden Gegenstände von einem Netzwerk in ein anderes überführt? Das ist der Punkt, wo Schaltungen zum Zug kommen.

Wir konstruieren zwei Netzwerke mit einer Kachel Lücke dazwischen. Nennen wir sie Netzwerk A und Netzwerk B. Die Gegenstände werden das Netzwerk wechseln mithilfe eines Stapelgreifers, der zwischen ein Anforderungskiste und einer aktiven Anbieterkiste sitzt. Für jeden Gegenstand, den wir von A nach B überführen wollen, stellen wir die Anforderung in A´s Anforderungskiste auf die Anzahl der Gegenstände ein, die wir überführen wollen. Wir können auf ähnliche Art und Weise auch Gegenstände von B nach A überführen.

Obwohl wir komplexe Schaltungen entwerfen können, um genau herauszufinden, welche Anzahl von welchen Gegenständen jeweils benötigt werden, bleiben wir hier jedoch bei einer einfachen Lösung, die für die meisten Anwendungen aber ausreicht: Wir halten beide Netzwerke bei der gleichen Anzahl an Gegenständen. Um das zu erreichen, bestimmen wir die Hälfte des Unterschiedes zwischen dem Bestand eines jeden Gegenstandes jedes Netzwerkes, und zwingen das Netzwerk mit mehr Gegenständen eines bestimmten Typs dazu, Gegenstände an das andere Netzwerk abzugeben. Hier ist ein schlechtes Diagramm, welches die Idee grundsätzlich darstellt:

Diagramm der Idee

Wir verbinden einen Roboterhangar in Netzwerk A mit einem Paar Kombinatoren für Berechnungen, einer multipliziert mit 1, der andere mit -1. Das gibt uns einen positiven und einen negativen Wert für die Gegenstände in einem Netzwerk. Das selbe tun wir für B.

Negierende Netzwerke

Wir verbinden jeweils den negativen Wert eines Netzwerks mit dem positiven Wert des anderen. Das gibt uns den Unterschied zwischen ihren Inventaren. Wir teilen dieses Signal dann durch 2 und schicken es an die Anforderungskisten. Es ist wichtig, das die Seite mit mehr Gegenständen ein positives Signal bekommt, sonst macht unser System genau das Gegenteil von dem, was wir eigentlich wollen. Es ist auch wichtig, das wir die Werte zu vielfachen der Tragkapazität der Roboter runden, sonst werden sie für immer hin- und herfliegen, um eine Differenz von zwei auszugleichen, indem sie immer vier Gegenstände bewegen.

Hälfte der Differenz berechnen

Da ein Greifer pro Richtung etwas langsam ist, können wir mehr hinzufügen. Wenn wir einfach blind mehr Kisten hinzufügen, ist die Anforderungsmenge jeder Kiste jeweils die Hälfte, die tatsächliche Anforderungsmenge ist dann ein Vielfaches des eigentlich gewünschten Wertes. Wir müssen also die Differenz durch die Anzahl der Kisten dividieren und den Rest dann bei einer Kiste mit hinzuaddieren. Auch hier ist es wieder wichtig, auf ein die Tragkapazität der Roboter zu runden. Diese Rundungen bedeuten, das die Netzwerke nicht perfekt gleich sein werden, aber das ist ein nötiges Opfer.

Mehrere Anforderungskisten

Diese Schaltung wird nun ihr bestes tun, um die Inhalte der Netzwerke gleichzuhalten, mit einem Fehler von einigen wenigen Gegenständen. Die Roboter werden etwas hin- und herfliegen, da es eine Verzögerung gibt, zwischen dem Entfernen der Gegenstände von einem Netzwerk und dem Hinzufügen zum anderen, was dazu führt, das zu Beginn etwas Überreagiert wird. Mit mehr als zwei Netzwerken ändert sich nicht viel. Da jedes Netzwerkpaar versucht, die Gegenstandsmenge auszugleichen, gleicht sich die Anzahl der Gegenstände mit der Zeit über alle Netzwerke hinweg aus.

Diese Schaltung ist unendlich erweiterbar und anpassbar. Man könnte einen Offset hinzufügen, um die Inhalte der Netzwerke in einem bestimmten Verhältnis zu halten, möglicherweise auch spezifisch für nur bestimmte Gegenstände, und natürlich noch was immer du willst zusätzlich. Meiner Meinung nach ist das noch viel wichtiger als die Einfachheit.

Züge: LTN-Analog in Vanilla

Gehen wir also von Robotern zu Zügen über: Züge sind sehr stark, aber auch dumm. In einem komplexen Netzwerk mit vielen Stationen mit gleichen Namen kommt man nicht an Schaltungen vorbei, da die Züge sonst immer wieder die selben Routen planen, und so einige Stationen überfüllen, während andere nichts abbekommen. Der konventionelle Weg, solche Probleme zu umgehen war es, die Stationen, welche gerade keine Züge benötigen, auszuschalten, um so die Züge zu anderen Routen zu zwingen. Das ist allerdings eine sehr ineffiziente Methode mit mehreren Problemen: Züge, welche innerhalb einer Kreuzung ihre Route ändern können zu Verstopfungen der Kreuzungen führen, das Einschalten einer einzelnen Station führt zu einer Lawine an Zügen, und extra Züge dieser Lawine führen zu weiteren Verstopfungen. Es gibt bereits Schaltungen, wie Haphollas’s Vanilla Train Network, welche einige dieser Probleme bekämpfen, aber nicht alle.

Der beliebte Weg, all diese Probleme zu bekämpfen, war die Verwendung von Mods. Einer der bekanntesten und einflussreichsten Mods für Factorio ist LTN, das logistische Zugnetzwerk (Logistik Train Network). Es implementiert im Prinzip das Gehirn eines Roboters in den Zug, und gibt den Stationen die Funktionen von Anbieter- und Anforderungskisten. Du stellst ein, was jede Station möchte, und der Zug kümmert sich um den Rest. Diese Mod führt natürlich zu einer unglaublichen Steigerung an Effizienz. Man könnte jetzt annehmen, das solche grundsätzlichen Änderungen nicht mit Kombinatoren zu implementieren sind, und man wäre korrekt. Es ist jedoch extrem einfach, ein viel einfacheres, wenn auch weniger effizientes, System zu implementieren.

Heute zeige ich deshalb “Train Limit Dispatcher and Requester”, oder kurz “TLDR”. Es ist eine Gruppe einfacher Schaltungen, die von mehreren Spielern unabhängig voneinander entwickelt wurden, welche von den in 1.1 hinzugefügten Zug-Limits gebrauch machen. Die hauptsächliche Vereinfachung besteht darin, das jeder Station und jedem Zug eine bestimmte Ressource zugeordnet wird. Die Logik ist simpel: Für jede Anbieterstation wird die Anzahl der Zuglagerungen berechnet, die bereit sind, und diese wird dann als Zuglimit eingestellt. Für jede Anforderung wird das selbe mit dem Unterschied zwischen gelagerten und benötigten Gegenständen getan. Jeder Zug verkehrt einfach nur zwischen Anbieter und Anforderung mit “Inventar voll” und “Inventar leer”.

Eine extrem einfache Anbieterstation
In diesem Beispiel wird die Anzahl der gelagerten Eisenplatten mit 16.000 dividiert, da das die Anzahl der Platten ist, die in vier Wagons passt.

TLDR löst alle Probleme, die die klassische Lösung mit deaktivierten Stationen hat. Züge werden keine Verstopfungen durch Routenumplanung in Kreuzungen verursachen, da im Gegensatz zum deaktivieren einer Station die Änderung des Zuglimits zu keiner Routenneuplanung führt. Eine übergroße Anzahl an Zügen wird niemals zu einer Station geschickt, da nur so viele wie das Zuglimit erlaubt die Station verlassen können. Keine Zuglavinen bedeutet weniger Verkehr, mehr Durchsatz und weniger benötigte Züge, was auch zu besserer Performance führt.

Allerdings ist nie etwas so einfach wie es klingt. Entlädt beispielsweise ein Zug an einer Anforderung, aber kein Anbieter ist gerade bereit, bleibt der Zug im Bahnhof stehen und schnürt so den Anforderer ab. Das bedeutet, wir benötigen ein zentrales Depot, so das Züge immer aus einer Anforderung heraus irgendwo hinfahren können. Das Depot kann so grundlegend wie möglich sein: einfach nur eine Menge Stationen mit einem konstanten Zuglimit von 1 und einigen Greifern zur Betankung. Züge fahren jetzt von Anforderer zum Anbieter und halten im Depot für einen kleinen Moment. Manche Züge halten auch im Depot nachdem sie den Anbieter verlassen haben, beispielsweise wenn die Anforderung sehr weit entfernt ist.

Ein Beispieldepot
Ein Beispieldepot für bis zu 100 Züge in einem Grid-freundlichen Format.

Aber warte, es gibt noch mehr. Warteraum vor Stationen ist nicht unbegrenzt, und wenn zu viele Züge auf einmal angefordert werden, könnte sich ein Rückstau bilden, da Züge auf Gleisen warten, wo niemals Irgendetwas warten sollte. Um das zu bekämpfen fügen wir zwei Kombinatoren für Vergleiche hinzu. Diese prüfen, ob die Anzahl der angeforderten Züge größer ist als eine feste Konstante. Falls dies der Fall ist, wird stattdessen die Konstante ausgegeben. Die Ausgänge werden summiert, einfach nur weil Konstante und Zuglimit verschiedene Signale nutzen, allerdings am Ende das selbe Signal sein müssen. Die Summe wird dann an die Station als Zuglimit übergeben.

Zuglimit-Limiter

Diese Schaltung ist, so wie bereits die anderen Schaltungen in diesem Artikel, individualisierbar. Du könntest beispielsweise die Anforderer automatisch selbstständig ihre eigenen Anforderungen einstellen lassen, oder die Anforderungen von etwas völlig anderem kontrollieren lassen, oder sogar die Anzahl der Gegenstände, die auf einen Zug geladen werden anpassen. Im Prinzip kannst du jede Konstante, die vom System genommen wird in dynamische Signale wandeln, welche von sich gegenseitig oder einer anderen Schaltung abhängen. Du kannst auch mit den Zugfahrplänen rumspielen, beispielsweise in dem Stationen automatisch aus der Planung entfernt werden, wenn ihr Bedarf gedeckt ist, oder so, das ein Zug mehrere Ressourcen abdeckt.

Abschlussgedanken

Die hier vorgestellten Schaltungen sollen sowohl ein fertig nutzbares Endprodukt, als auch die Grundlage für eigenen Schaltungsprojekte darstellen. Ich würde sagen, sie sind ähnlich zu noch unbemalten Figuren: Man kann viel daraus bekommen, auch in der Form wie man sie erhalten hat, aber man hat unendliche Möglichkeiten, sobald man etwas Kreativität und Können herausholt. Es gibt absichtlich keine Blaupausen in diesem Artikel, da das Ziel ist, dass du die Schaltungen verstehst und nicht nur einfach Blaupausen nachbaust. Viel Spaß beim Verkabeln!

Beitragen

Wie immer suchen wir nach Leuten, die zu Alt-F4 beitragen wollen, sei es mit einem Artikel oder durch Hilfe bei Übersetzungen. Wenn du etwas Interessantes im Kopf hast, das du mit der Community in einer eleganten Art teilen möchtest, hier kannst du das tun. Falls du dir unsicher bist, beantworten wir gerne Fragen zu Inhalt und Struktur. Falls das nach etwas klingt, woran du interessiert bist, tritt unserem Discord bei, um es nicht zu verpassen!