Wie soll eine Schaltung oder ein Stromversorgungssystem (wie Redstone in Minecraft) implementiert werden?

8

Ich möchte ein Energiesystem wie das Redstone-System in Minecraft implementieren.

Ich habe n Stromquellen und m Kabel. Wenn ich die Stromquelle oder ein Kabel abtrenne, sollte sich der Stromkreis ausschalten. Modell des Kabelsystems

Wie vermeide ich Kreise? Wenn jedes Kabel mit dem Status "Ein" die in der Nähe befindlichen Kabel mit Strom versorgt, kann ich unendliche Kreise erstellen, in denen keine Stromquelle beteiligt ist (siehe Bild). Plus Seite ist, dass es in T = m läuft

Ich könnte ab jeder Stromquelle einen Stromstoß durch die Grafik senden und bei jedem Update-Aufruf jedes Kabel ausschalten. Problem ist, dass es in T = n * m läuft.

Gibt es eine bewährte Methode? In Minecraft war das Redstone-System sehr langsam, daher habe ich etwas übersehen.

BEARBEITEN: Das System sollte ohne entfernungsbasierten Zerfall funktionieren.

Benedikt S. Vogler
quelle
Dies hängt davon ab, welches Modell Sie implementieren möchten. Beispielsweise könnte eine Stromquelle x Energieeinheiten bereitstellen, die bei Verwendung verbraucht werden. Ein anderes Modell ist, dass Ihre Stromquelle ein Potenzial hat, das die Last begrenzt, die Sie auf den Stromkreis legen können, der funktioniert, solange Sie Ihre Stromquelle mit Strom versorgen.
user3730788

Antworten:

7

Rekursive Ausbreitung. Zum Beispiel haben Sie eine Lampe, die über N Kabelobjekte mit einer Batterie verbunden ist. Die Lampe fragt das N-te Kabel, ob es mit Strom versorgt wird (dies ist das Kabel, das direkt an die Lampe angeschlossen ist). Das N-te Kabel fragt dann das N-1-Kabel, ob es mit Strom versorgt wird und so weiter. Jedes Mal, wenn ein Objekt gefragt wird, ob es mit Strom versorgt wird oder nicht, setzt es eine lastEvaluatedVariable auf die aktuelle Frame-Zeit. Die Rekursion endet auf einem Endknoten wie einer Batterie oder wenn sie ein Objekt erreicht, das bereits in diesem Frame ausgewertet wurde (dies vermeidet eine unendliche Rekursion). Diese Weitergaben treten nur auf, wenn sich das System ändert. Zu den Änderungen gehört das Hinzufügen / Entfernen von Teilen oder Schaltern, die umgeschaltet werden.

Bei diesem System gibt es keinen Abstandsabfall oder ähnliche Einschränkungen. Ich habe es verwendet, um einen Logikgattersimulator zu erstellen, und es funktioniert für verschiedene Logikbeispiele wie ein Flip-Flop.

MichaelHouse
quelle
Diese. Außerdem würde ich einen Verweis auf die Powersource hinzufügen. Wenn ein Element geändert wird, teilen Sie der Quelle mit, auf die verwiesen wird, das zu aktualisierende Netzwerk mit. Auf diese Weise müssen Sie nicht nur aktualisieren, wenn sich etwas ändert, sondern Sie wissen auch, welche Elemente betroffen sind. Änderungen in Ihrem Netzwerk können auch leicht identifiziert werden: Würde eine Änderung eine Neubewertung erfordern oder nicht usw.
Felsir
@Felsir Das könntest du machen, aber ich würde es nicht empfehlen. Es erhöht die Komplexität ohne großen Gewinn. Es kann mehrere Stromquellen und mehrere Senken pro Quelle geben. Es wäre einfacher, nur der Bewertung zu vertrauen, und es ist wirklich nicht so ressourcenintensiv.
MichaelHouse
Der Lösung fehlt eines, denke ich: Wenn Sie ein Kabel in der Mitte haben und eines mit Strom versorgt wird und das andere Ende nicht nur eines hat, wird das Wechselgeld erhalten. Sie haben im Grunde genommen einen Baum mit der Variablen "lastEvauluated" erstellt, indem Sie Kreise entfernt haben. Jetzt breitet sich die Änderung im Baum nach oben aus, aber nicht nach unten. Ich werde es in meiner Implementierung versuchen, indem ich die Änderungen nach dem Hochziehen nach unten drücke.
Benedikt S. Vogler
Ich habe die Lösung zu Ihrer Antwort in einer Bearbeitung hinzugefügt, da meine Hinzufügung zum Algorithmus funktioniert.
Benedikt S. Vogler
1
@ Benedikt Sie beschreiben das erwartete Verhalten. Das liegt daran, dass mein System Ein- und Ausgänge verwendet. UND-Gatter und ODER-Gatter sind nicht bidirektional (diese verwenden die Diodenimplementierung). Wenn ich also wollte, dass die Energie zu etwas jenseits des B-Knotens gelangt, würde ich einen Ausgang auf diese Weise lenken. Ich würde vorschlagen, dass Sie eine neue Antwort erstellen, um Ihr bidirektionales System zu beschreiben.
MichaelHouse
2

In Minecraft gibt es einen entfernungsbasierten Zerfall mit einer sehr kurzen Zerfallsentfernung (16 Blocks Reichweite).

Was Sie brauchen, ist ein Konnektivitätstest zwischen Grafiken .

Eine Möglichkeit wäre, wiederholt jede Kante zu nehmen und die verbundenen Knoten zu einem einzigen Knoten zu kombinieren. Nachdem alle Kanten verschwunden sind, erhalten Sie für jedes Netzwerk einen Knoten. Dann ist das Senden von Strom trivial.

Ratschenfreak
quelle
Das Speichern eines Untergraphen in einem Knoten scheint sehr klug zu sein, ich muss jedoch ein wenig über eine konkrete Implementierung nachdenken, da diese Antwort etwas vage erscheint und nur den "Konnektivitätstest zwischen Graphen" erwähnt, der ein ziemlich wichtiger Teil dieser Lösung zu sein scheint.
Benedikt S. Vogler
Tatsächlich ist diese Beschreibung eine Variante von Kargers Algorithmus zum Auffinden von Min-Schnitten. Stattdessen fahren Sie fort, bis keine Kanten mehr zu kontrahieren sind.
Ratschenfreak
1

Ein mit Strom versorgter Block verfügt über mehrere Eingangs- / Ausgangsanschlüsse, aber an einem Startpunkt wissen wir nicht, wann er ein- oder ausgegeben wird.

Jeder Block hat eine "Spannung", die die Energie ist, die zu ihm kommt, abzüglich des Verlusts / Verbrauchs.

Ein mit Strom versorgter Block versorgt alle umgebenden Blöcke mit Strom, und jeder Block nimmt die höhere Spannung von den umgebenden Blöcken als Eingang. Sie könnten das System auch komplizieren, indem Sie eine Intensität definieren, aber ich werde der Einfachheit halber nur bei Voltage bleiben.

Jedes Mal, wenn eine Änderung an der Schaltung durch Hinzufügen / Entfernen von Blöcken oder durch die Schaltung selbst durchgeführt wird, muss die Änderung bis zur Stabilität auf die gesamte Schaltung übertragen werden.

Ich würde Ihnen vorschlagen, eine Schnittstelle für jedes angetriebene Objekt (Cube in MC) zu entwerfen:

class PowerInterface
{
protected:
    std::vector<shared_ptr<PowerInterface>> sibling;

    double energy=0;
    bool   isActive = false;

    virtual void propagate(double inEnergy) = 0;

    virtual void addSibling(shared_ptr<PowerInterface> newSibling) = 0;
    virtual void removeSibling( shared_ptr<PowerInterface> remSibling) =0;
};

Angenommen, Sie implementieren addSibling und removeSibling. Der wichtigste Teil ist die Propagate-Funktion:

void PoweredCube::propagate( double inEnergy ) 
{
    // Define the behaviour
    energy = inEnergy-1.0; // Normal device
    energy = inEnergy-0.1; // Normal cable
    energy = 10.0;         // Normal source of power.

    if (energy<0.0)
    { 
        energy = 0.0;
        isActive = false;
        // No energy, so do not propagate anymore
        return;
    }
    isActive = true;

    // Propagate
    for (auto &s: sibling)
    {
        // Only propagate to sibling with less energy. 
        if (energy > s->energy) s->propagate( energy);
    }
}

Als rekursive Lösung sollte jeder Block die Energie ein wenig reduzieren, niemals erhöhen. Die Stromquelle kann einen festen Wert einstellen, jedoch niemals basierend auf den Eingaben erhöhen. Das sollte kein Problem sein, da alle "echten" Systeme auf diese Weise funktionieren.

Adrian Maire
quelle
Bei dieser Lösung benötigt jede Schleife jedoch "n = 1 / Abnahme" -Aufrufe, bevor sie heruntergefahren wird. Ist das nicht ein bisschen teuer?
Benedikt S. Vogler
Nein, Sie aktualisieren nur bei Änderungen: wenn Sie einen Block erstellen / löschen / bearbeiten oder wenn ein Block eine aktive Änderung erzeugt. Wenn Sie sich den Code ansehen, werden die meisten Änderungen nur wenige Blöcke weitergeben. Natürlich könnten Sie das Diagramm vereinfachen, wie der @ BenediktS.Vogler sagt, aber meiner Meinung nach wird es schon ziemlich schnell sein. Nehmen wir 1000 aktive Blöcke in der aktiven Zone an, was bereits ein riesiger Mechanismus ist. Selbst im schlimmsten Fall eines vollständigen Updates sind es nur wenige Operationen * 1000, was kurz ist. Normalerweise werden nur wenige Blöcke aktualisiert
Adrian Maire