Startseite > Root > Log book > Bedingungen verwalten
Bedingungen verwalten
Samstag 30. November 2024, von
Alle Fassungen dieses Artikels: [Deutsch] [English] [français]
Nun, es sieht so aus, als würde dieser Blog zu Projektnotizen werden. Sollte ich mir Sorgen machen? Vielleicht nicht. Jedenfalls habe ich meinen Dia-nach-RenPY-Übersetzer, genannt DiaVN, weiter entwickelt. Aber die Übersetzung von einem Paradigma in ein anderes kann zu Problemen führen. Heute werde ich erörtern, wie man mit den Bedingungen umgeht.
Um das zu verstehen, sollten wir zu den wirklichen Grundlagen zurückkehren. Was ist ein Programm, wenn nicht eine Folge von Schritten, von denen jeder den Zustand des Computers verändert, auf dem er ausgeführt wird? Stellen Sie sich vor, Ihr Computer hat Füße, und Sie wollen ihn auffordern, eine Meile zu laufen. Sie schreiben ein Programm mit tausend „Geh einen Schritt vorwärts“-Anweisungen, etwa so:
mach einen Schritt
mach einen Schritt
mach einen Schritt
mach einen Schritt
mach einen Schritt
mach einen Schritt
mach einen Schritt
mach einen Schritt
mach einen Schritt
... // 990 Zeilen später...
mach einen Schritt
pfui
Wie wäre es, wenn wir unseren bestehenden Code wiederverwenden könnten, anstatt die gleiche Zeile immer wieder neu zu schreiben? Das Konzept einer „Schleife“ ermöglicht genau das. Fügen wir die Schleife hinzu:
mach einen Schritt
gehe zurück zur vorherigen Zeile
pfui
Nun kommen wir zu unserem heutigen Problem: Wie kann man dem Computer mit der obigen Schleife sagen, dass er aufhören soll, nachdem die Meile zurückgelegt ist? In diesem Fall wird der Computer fröhlich bis ins Unendliche laufen (oder zumindest so weit, wie ihn sein Stromkabel tragen kann). er wird niemals „pfui“ sagen.
Wir müssen also ein zweites Element zu unserem Programm hinzufügen: eine Bedingung. Dabei handelt es sich um eine spezielle Anweisung, die den Zustand des Computers überprüfen und den Programmablauf in Abhängigkeit von diesem Zustand ändern kann. Hier ist das endgültige Programm mit einer Schleife und einer Bedingung:
Mach einen Schritt
sind wir schon eine Meile gelaufen?
nein : gehe zurück zur ersten Zeile
ja : pfui
Wohoo, wir haben gerade Basic erfunden! *hust*
Was macht DiaVN also? Es ermöglicht die Darstellung von Programmen mit Hilfe von Diagrammen anstelle von Textzeilen. Genauer gesagt, stellt jedes Element des Diagramms eine Aktion dar (in gewisser Weise wie eine Linie). Jeder Pfeil zwischen zwei Elementen stellt den Programmablauf dar. Die Idee dahinter ist, dass man Programme (in diesem Fall Abenteuerspiele) weniger linera erstellen kann als die, die man mit Text programmieren muss (siehe Eine Visual Novel, die mit einem Tool zur Diagrammerstellung erstellt wurde?). In der heutigen Ausgabe geht es also um die Darstellung von Bedingungen in DiaVN.
Fangen wir an. DiaVN erzeugt RenPY-kompatiblen Code, und RenPY ist mehr oder weniger Python. Die Bedingungsanweisung in Python ist sehr weit gefasst. In Dia stelle ich eine Bedingung durch eine Losange dar und jede mögliche Lösung (wie das obige Ja/Nein) durch Pfeile, die die Losange verlassen und auf ein anderes Element zeigen. Auf diese Weise kann sich der Fluss „verzweigen“.
Ich könnte beschließen, dem Benutzer die Möglichkeit zu geben, in das Bedingungselement zu schreiben, was immer er will, und dann die Verzweigungen frei zu beschriften und zu hoffen, dass der Übersetzer all dies in einen brauchbaren RenPY-Code kopiert. Das ist der „I don’t give a fsck“-Ansatz, bei dem DiaVN nur als Werkzeug zur Verwaltung der Abläufe verwendet wird und jedes Element einfach ein Wrapper für ungeprüften RenPY/Python-Code ist.
Mein erstes Problem ist, dass ich hoffe, mit DiaVN eines Tages Code für etwas anderes als RenPY zu erzeugen (letztendlich ein Spiel für den Neo Geo Pocket Color, also Assembler-Code). Wenn ich nur RenPY-Code einpacke, kann ich mein Spiel nicht einfach auf die beiden Plattformen portieren - ich müsste auch einen RenPY zu NGPC Konverter schreiben.
Das zweite Problem ist, dass die Verwendung von diaVN als Wrapper um den RenPY-Code es sehr schwer machen wird, das Spiel zu debuggen, wenn unweigerlich Probleme auftreten werden. Der RenPY-Interpreter zeigt Fehler in den Zeilennummern an, die dem von DiaVN automatisch generierten Code entsprechen, und für den Benutzer wird es dann kompliziert, den automatischen Code zu lesen und herauszufinden, welches Element aus dem Diagramm passt, besonders wenn das Projekt größer wird. Und bei welchen Elementen ist die Wahrscheinlichkeit von Fehlern am größten? Nun, diejenigen, bei denen der RenPY-Code in Wirklichkeit Python-Code ist, d.h. die Bedingungen.
Deshalb habe ich beschlossen, die Bedingungen für die Arbeit mit DiaVN einzuschränken. Der Benutzer wird nur 3 Möglichkeiten haben:
- Er kann eine (im Bedingungselement enthaltene) Variable mit einem unmittelbaren Wert (Zahl oder Zeichenkette) oder einer anderen Variablen vergleichen. Wenn keine Komparatoren angegeben werden, wird jeder Wert mit einem impliziten „Gleichheitszeichen“ verglichen.
- dieselbe Methode, aber jedem verglichenen Element wird ein Komparator vorangestellt (< > <= >= == !=), um z. B. Bereiche überprüfen zu können.
- das Element kann einen Python-Ausdruck enthalten, der True oder False zurückgeben kann
Es wurde festgestellt, dass die dritte Möglichkeit dem Benutzer viel Spielraum lässt, um ein Python-Durcheinander zu verursachen (daher sollte eine Warnung ausgegeben werden).
Das Problem der Listen
All dies ist gut, aber es gibt ein Problem bei diesem Problem. In vielen Programmiersprachen, wie z.B. Python und damit auch RenPY, „wissen“ wir nicht im Voraus, was in einer Variablen steht. Ist es eine ganze Zahl? Eine Zeichenkette? A... Liste?
Python überlässt dem Benutzer die Verantwortung, in seinem Programm keine Fehler zu machen, und erzeugt manchmal keine Fehler, wenn inkompatible Typen verglichen werden (z.B. ist der Vergleich der Ganzzahl 1 mit der Zeichenkette, die eine „1“ enthält, erlaubt, liefert aber false).
Das können wir noch hinbekommen. Ein Problem ergibt sich jedoch, wenn wir das für den Vergleich verwendete Symbol je nach Elementtyp ändern müssen. Dies ist bei Listen der Fall.
Eine Liste ist also ein Element, das eine Folge von anderen Elementen enthält (jedes kann auch eine Liste sein). Wenn ein Benutzer eine Variable mit einer Liste vergleicht, möchte er in der Regel wissen, ob der in der Variablen enthaltene Wert irgendwo in der Liste enthalten ist. In unserem Fall müssen wir dafür einen speziellen Operator in Python verwenden, den „in“-Operator. Und der einzige Weg, um zu verstehen, was der Benutzer tun will, ist, den Typ der Variablen im Voraus zu kennen...
Wir könnten dieses Problem also entweder dadurch lösen:
- die Verwendung von Listen verbieten
oder
- DiaVN ein gewisses Vorwissen darüber geben, was Variablen enthalten.
Im Jahr 2024 ist es vielleicht ein wenig beschämend, die Verwendung von Listen zu verbieten. Wir müssen also in DiaVN entweder die Typdeklaration von Variablen oder ein spezielles Schlüsselwort einführen, das beim Vergleich anzeigt, dass das Element eine Liste ist. Wir könnten auch die Möglichkeiten von Python nutzen, die Elementtypen zur Laufzeit vergleichen und dann die richtige Bedingung je nach Situation ausführen. Aber das würde wohl eine Menge Zeit kosten und den generierten Code noch schwerer lesbar machen.
Da ich ein wenig altmodisch bin, werde ich mich für die erste Möglichkeit entscheiden. Ich denke, ich werde nach den Variablennamen fragen, um damit zu beginnen:
- i_ : Integer-Zahl
* f_ : Gleitkommazahl (Float)
* s_ : Zeichenkette (String) - l_ : Liste
Und die entsprechenden unmittelbaren Werte:
- Integer-Zahl : 42
- Gleitkommazahl : 0.1 (um eine ganze Zahl als float darzustellen, 1.0)
- Zeichenkette : „Hallo, Welt“
- Liste : [42, -63, 28, 12] (hier eine Liste von Ganzzahlen)
Aber was machen wir mit Listen gemischten Typs, Listen, die Variablen enthalten, Listen, die andere Listen enthalten...?
Halten wir uns vorerst an folgende Einschränkung: eine Liste ist eine Liste von Elementen desselben Typs, und sie kann keine anderen Listen enthalten.
Nun, was für ein Tag...