====== Variablen ======
Variablen sind Behälter für einen beliebigen Wert, den man mit Lua ausdrücken kann. Eine Variable besteht aus ihrem **Namen** (Key) und ihrem **Inhalt** (Value). Über ihren Namen kann eine Variable eindeutig identifiziert bzw. ihr Inhalt abgerufen werden. \\
In Lua wird eine Variable definiert, indem ihr Name, gefolgt von einem =-Zeichen, einem Wert zugewiesen wird.
Ein Beispiel:
Result = 42
Der Name dieser Variable ist //Result//, ihr Inhalt //42//. Eine Variable auf diese Art zu definieren wird auch **Zuweisung** genannt, wie im [[ scripting:tutorials:level1:programming_intro#einfaches_beispielkochrezept | Kochrezeptbeispiel ]] erklärt.
Beim Namen für eine Variable ist zu beachten, dass zwischen Groß- und Kleinschreibung unterschieden wird. Folgender Code würde zwei verschiedene Variablen erschaffen, die nichts miteinander zu tun haben:
Result = 42
result = 41
Auch dürfen in Variablennamen ausschließlich Groß- und Kleinbuchstaben (ausgenommen Umlaute), Ziffern und der Unterstrich vorkommen. Der Variablenname darf nicht mit einer Ziffer beginnen. Wir listen einige gültige und ungültige Variablennamen im folgenden Beispiel auf:
Result = 42 -- gültig
_Result = 42 -- gültig
R3su1t = 42 -- gültig
4tytwo = 42 -- ungültig!
Zaubärzahl = 42 -- ungültig!
-- Wir verwenden ab jetzt regelmäßig diese Kommentare in Codebeispielen.
-- Kommentare sind kein Programmcode, sondern machen den gegebenen Code durch
-- unterstützende Erklärungen besser verständlich.
-- Kommentare werden in Lua mit -- eingeleitet
**Wichtig**: Einige Namen für Variablen sind unzulässig, da sie von Lua intern reserviert sind. Alle unzulässigen Namen sind hier aufgelistet:
| **and** | **break** | **do** | **else** | **elseif** | **end** | **false** |
| **for** | **function** | **if** | **in** | **local** | **nil** | **not** |
| **or** | **repeat** | **return** | **then** | **true** | **until** | **while** |
**Wichtig**: Das =-Zeichen bei der Variablenzuweisung hat nichts mit dem =-Zeichen zu tun, wie man es aus der Mathematik kennt. Man kann nicht einfach ein Gleichungssystem ins Skript tippen, das dann vom Programm gelöst wird! \\
Eine Zuweisung arbeitet in einer fest vorgegebenen Reihenfolge:
- Nimm den Wert, der rechts vom =-Zeichen steht
- Speichere diesen Wert unter dem Namen, der auf der linken Seite steht, ab
Dementsprechend müssen die Werte, die jeweils links und rechts vom = stehen, nicht notwendigerweise gleich sein. Dies wird offensichtlich, wenn man beginnt, mit Variablen zu rechnen. Dazu folgen nun einige Kapitel für die jeweiligen Datentypen, die eine Variable halten kann.
----
**Hinweis**: Unsere Beispiele in diesem und den folgenden Kapiteln können besser nachvollzogen werden, wenn man die Programmzeilen nebenbei ausprobieren kann. Dazu kann man diese Webseite hier verwenden:
[[ https://www.lua.org/demo.html ]]
Um dabei bei der Ausgabe ein Ergebnis zu sehen, kann man ''print'' verwenden. Will man beispielsweise die Variable ''Result'' ansehen, kann man
Result = 42
print(Result)
schreiben. Wenn die Variable einen anderen Namen hat, muss man diesen dementsprechend austauschen.
----
===== Zahlen =====
Lua kann sowohl mit ganzen Zahlen als auch Dezimalzahlen arbeiten. Bei letzteren ist zu beachten, dass das Dezimaltrennzeichen kein Komma, sondern ein Punkt ist:
DecimalNumber = 4.2
Für Zahlen stehen in Lua die gängigen Rechenoperationen zur Verfügung:
^ Zeichen ^ Rechenoperation ^ Beispiel ^
| **+** | Addition | Result = 40 + 2
|
| **-** | Subtraktion | Result = 48 - 6
|
| ** * ** | Multiplikation | Result = 7 * 6
|
| **/** | Division | Result = 84 / 2
|
| **^** | Exponentiation | Result = 3.4761^3
|
| **-** | Negation (einzelner Wert) | Result = - (- 42)
|
Im letzten Beispiel haben wir noch Klammern eingesetzt, um die Berechnungsreihenfolge festzulegen. Ohne Klammerung gilt Punkt vor Strich (bzw. Exponentiation hat die höchste Priorität von allen). Für einige weitere mathematische Operationen siehe die [[ scripting:reference:standard_library:math|math-Übersicht]].
Wenn man mehr als eine Variable hat, kann man diese auch untereinander verrechnen:
FirstNumber = 32
SecondNumber = 2
ThirdNumber = 0.5
FourthNumber = 10.5
Result = ( FirstNumber / SecondNumber )^ThirdNumber * FourthNumber
An folgendem Beispiel kann man leicht erkennen, dass das =-Zeichen der Zuweisung dient und keinen mathematisch korrekten Ausdruck formuliert:
FirstNumber = 5
-- Berechne zuerst den Wert rechts vom = : Das ergibt 15, weil FirstNumber zu dem
-- Zeitpunkt noch den Wert 5 hat. Erst danach wird 15 als die neue FirstNumber abgespeichert
FirstNumber = FirstNumber + 10
SecondNumber = FirstNumber - 3
SecondNumber = SecondNumber / 2
ThirdNumber = FirstNumber * SecondNumber
ThirdNumber = ThirdNumber - 48
----
===== Strings =====
Strings sind Zeichenketten und werden meistens für die Darstellung von Text verwendet. Strings beginnen und enden mit Anführungszeichen:
Text = "Hallo Welt"
Strings können mit zwei aufeinanderfolgenden Punkten miteinander verkettet werden:
Text1 = "Hallo "
Text2 = "Welt"
Text3 = Text1..Text2
Auf diese Art verkettet können auch Variablen mit Zahlenwert in einen String eingefügt werden:
MyNumber = 42
Text = "Die Antwort lautet "..MyNumber.."! Großartig!"
Es gibt einige Zeichen, die in einem String nicht ohne Weiteres verwendet werden können. Eines davon ist logischerweise das Anführungszeichen, da es einen String beendet bzw. einleitet. Um ein Anführungszeichen dennoch in einem String verwenden zu können, muss es mit einem Backslash "escaped" werden:
-- Wir haben hier den Text in zwei Zeilen geschrieben und mit .. miteinander verbunden, um
-- horizontales Scrollen zu vermeiden. Dies sorgt in Skripten für bessere Übersicht
DrEvil = "Back in the sixties I developed a weather changing machine which was, in essence, "..
"a sophisticated heat beam which we called a \"laser\""
Ein anderes Zeichen, das in Strings nicht einfach verwendet werden kann, ist als Resultat der Backslash. Ein einzelner Backslash muss daher mit zwei Backslashes definiert werden. Das ist vor allem bei der Angabe von Dateipfaden wichtig:
Path = "C:\\Games\\SettlersHoK"
----
===== Booleans =====
Booleans können nur einen von zwei verschiedenen Werten annehmen: Wahr (**true**) oder Falsch (**false**). Damit wird der Wahrheitsgehalt einer Aussage ausgedrückt. [[ scripting:tutorials:level1:branches|Verzweigungen]] und [[ scripting:tutorials:level1:loops|Schleifen]] funktionieren nur, indem sie Bedingungen prüfen. So eine Bedingung kann zum Beispiel sein, ob sich ein Siedler in der Nähe einer bestimmten Position befindet. Die Antwort darauf ist entweder Wahr oder Falsch.
CatsAreCute = true
FeathersAreHeavy = false
==== Logische Operatoren ====
Mit booleans kann man auch "rechnen". Lua bietet dafür drei verschiedene Funktionen an (im Weiteren logische Operatoren genannt):
Und (**and**) prüft, ob zwei verschiedene Booleans beide wahr sind.
Result = Boolean1 and Boolean2
^ and ^^^
^ Boolean1 ^ Boolean2 ^ Result ^
| false | false | false |
| false | true | false |
| true | false | false |
| true | true | true |
Oder (**or**) prüft, ob von zwei verschiedenen Booleans mindestens einer wahr ist.
Result = Boolean1 or Boolean2
^ or ^^^
^ Boolean1 ^ Boolean2 ^ Result ^
| false | false | false |
| false | true | true |
| true | false | true |
| true | true | true |
Nicht (**not**) kehrt den Wert eines Booleans um.
Result = not Boolean1
^ not ^^
^ Boolean1 ^ Result ^
| false | true |
| true | false |
==== Vergleichsoperatoren ====
Sowohl Zahlen als auch Strings können miteinander verglichen werden, was ebenfalls in Booleans resultiert. Ein einfaches Beispiel ist hierbei die Frage, ob eine Zahl größer als eine andere ist:
Test = Number1 > Number2
Etwas ungewohnter ist die Frage, ob ein Text "größer" als ein anderer ist. Strings sind lexikographisch geordnet, quasi wie in einem Wörterbuch. Wörter, die mit "A" beginnen, sind kleiner als Wörter, die mit "B" beginnen. Sind die ersten Buchstaben gleich, werden die zweiten verglichen, usw:
Test = "Hallo" < "Welt" -- true
Eine vollständige Liste aller Vergleichsoperatoren findest du hier:
^ Operator ^ Bedeutung ^ Beispiel ^
| < | a kleiner b? | Test = a < b
|
| > | a größer b? | Test = a > b
|
| <= | a kleiner oder gleich b? | Test = a <= b
|
| >= | a größer oder gleich b? | Test = a >= b
|
| == | a gleich b? | Test = a == b
|
| ~= | a ungleich b? | Test = a ~= b
|
Besonderes Augenmerk sei darauf gerichtet, dass die Frage nach Gleichheit mit **zwei** ==-Zeichen geschieht, da ein einzelnes =-Zeichen bereits für die Zuweisung reserviert ist.
Wenn du Variablen unterschiedlicher Datentypen miteinander vergleichst, bekommst du in der Regel eines von zwei verschiedenen Ergebnissen:
- Ein Fehler. "0" < 1 ist kein gültiger Ausdruck, da ein String mit einer Zahl verglichen werden soll
- **false**. "0" == 0 wirft keinen Fehler, da die beiden Eingabewerte nicht in ihrer "Größe" miteinander verglichen, sondern nur deren Gleichheit festgestellt werden soll. Da ein String und eine Zahl intern aber völlig anders dargestellt werden, ist das Ergebnis negativ.
Achte deshalb immer darauf, dass deine Variablen vom richtigen Typ sind.
==== Berechnungsreihenfolge ====
Diese logischen Operatoren haben ebenfalls eine "Punkt vor Strich"-Reihenfolge, die es (zusammen mit den Rechenoperationen) zu beachten gilt:
- Exponentiation
- **not** und Zahlennegation
- Punktrechnung
- Strichrechnung
- Stringkonkatenation
- Vergleichesoperatoren
- **and**
- **or**
Wobei höhere Priorität bedeutet, dass ein Operator vor einem anderen mit niedrigerer Priorität ausgeführt wird. Andere Reihenfolgen lassen sich ebenfalls mit Klammerung umsetzen:
Boolean1 = true
Boolean2 = false
Number1 = 5
Number2 = 8
Number3 = 13
Result1 = not Boolean1 and Boolean2 or Number3 > Number1*Number2
Result2 = ((not Boolean1) and Boolean2) or (Number3 > (Number1*Number2))
Result3 = not (Boolean1 and Boolean2) or (Number3 > (Number1*Number2))
-- Test1 ist wahr, da Result2 so geklammert ist, wie es ohnehin ausgerechnet werden würde
Test1 = Result1 == Result2
-- Test2 ist falsch, da die Klammerung bei Result3 für ein anderes Ergebnis sorgt
Test2 = Result1 == Result3
**Achtung**: Besondere Vorsicht ist geboten, wenn verschiedene Datentypen miteinander in Berührung kommen:
Test = not 5 > 7
Ohne Klammerung wird hier zuerst **not** 5 ausgewertet, was **false** ergibt. Dann wird geprüft, ob false > 7 ist, was in einem Laufzeitfehler resultiert. Der Ausdruck muss daher korrekt geklammert werden:
Test = not (5 > 7)
----
===== Nil =====
Ein weiterer Datentyp ist **nil**. Der Zweck dieses Datentyps ist einzig und allein, sich von allen anderen Datentypen zu unterscheiden und wird in der Regel benutzt, wenn keine sinnvollen Daten angegeben werden können:
Unicorns = nil
----
===== Tables und Funktionen =====
Der Vollständigkeit halber bleibt zu erwähnen, dass auch [[ scripting:tutorials:level1:tables|Tables]] und [[ scripting:tutorials:level1:functions_blocks|Funktionen]] Variablen sind. Die Erklärungen dazu finden sich in den entsprechenden Kapiteln.
----
Im nächsten Kapitel beschreiben wir, wie Programmcode nur unter bestimmten Bedingungen ausgeführt wird.
[[ scripting:tutorials:level1:programming_intro | Voriges Kapitel: Was ist Programmierung ]]\\
[[ scripting:tutorials:level1:branches | Nächstes Kapitel: Verzweigungen ]]\\
[[ scripting:tutorials:level1:variables | Zurück nach oben ]]