Die Vorlage-Metabefehlsauswertung ermöglicht überall innerhalb der Metabefehle oder darin eingebetteter Spiel-Befehle die Verwendung von Ausdrücken. Dadurch kann man Parameter für Befehle berechnen, anstatt auf feste Werte begrenzt zu sein.
Dabei gibt es folgende Operatoren (höchste Priorität oben):
( ) | Klammerung |
$( ) | Inplace-Auswertung für Objektzugriffe |
+ - ! | Vorzeichen und logisches Nicht |
^ | Potenzierung |
* / % | Multiplikation, Division, Modulo (Rest) |
+ - | Addition, Subtraktion |
< <= == >= > != | Vergleichsoperatoren |
&& || | Logische Und- bzw. Oder-Verknüpfung |
& | | Veraltet: Logische Und- bzw. Oder-Verknüpfung |
Ein paar Worte zum Operator / : Soll eine ganze Zahl durch eine ganze Zahl dividiert werden, so liefert die zugehörige Rechenoperation lediglich den ganzzahligen Anteil der Division. Als Beispiel: 7/2 liefert 3 als Ergebnis.
Zu beachten ist weiterhin, dass bei Verwendung aller Rechenoperatoren (^ * / % + - ) die beteiligten Operanden (Zahlen) von Vorlage intern vor Durchführung der Berechnung in gleiche Typen umgewandelt werden und das Ergebnis der Berechnung als Zahl von diesem Typ zurückgegeben wird. Ausschlaggebend ist hierbei der Typ der linken Zahl. Ein Beispiel: 7/2.0=3, da der Typ der linken Zahl ganzzahlig ist, somit also die rechte Zahl (2.0) in den Typ der linken Zahl konvertiert wird (also zu 2) und erst dann die Berechnung und somit eine Ganzzahldivision durchgeführt wird. Dem gegenüber ergibt 7.0/2 das (zu erwartende) Ergebnis 3.5. Findet eine Typkonvertierung statt, so werden (im eigentlich einzig interessanten Fall) einer Fließkommazahl die Nachkommastellen abgeschnitten, wenn sie in eine ganze Zahl umgewandelt wird.
ACHTUNG: Innerhalb von Ausdrücken dürfen keine Leerzeichen verwendet werden, da die Teile sonst als verschiedene Parameter des Befehls bzw. Metabefehls gesehen werden, denn Eressea verwendet ja nur das Leerzeichen als Parameter-Trenner. Also #if $eins==$zwei&$zwei==$drei statt #if $eins == $zwei & $zwei == $drei
Typen sind unterschiedliche Darstellungsweisen von Werten. Manche Werte (z.B. Namen) lassen sich nur als Text sinnvoll ablegen, ein dazu passender Typ wäre String. Zahlen hingegen können manchmal in verschiedenen Varianten gespeichert und verarbeitet werden. Vor allem unterscheidet man hierbei Zahlen mit und ohne Nachkommaanteil. Erstere sind Fließkommazahlen, letztere Ganzzahlen.
Vorlage kennt verschiedene Typen mit denen Werte oder Wertegruppen abgebildet werden können. Dies sind (Beispiel in Klammern):
Integer (4711) | Ganzzahlen von -2147483648 bis 2147483647 |
Float (23.5) | Fließkommazahlen mit min. 10 Stellen Genauigkeit und einem Wertebereich von 1e-50 bis 1e+50 (Wichtig: Es wird der Punkt und nicht das Komma verwendet um Vor- und Nachkommastellen zu trennen) |
String ('Hallo!') | Texte von nahezu bel. Länge (abhängig vom Speicherplatz) |
Array ([1,'Huhu',3.14]) | Felder mit nahezu bel. vielen Werten beliebigen Typs, die auch wiederum Array oder Dictionaries enthalten dürfen (siehe auch #array) |
Dictionary (keine Literalform) | Felder die wie Arrays bel. Typen enthalten können, auf deren Inhalt man über einen Schlüssel (ein Wert) zugreifen kann (siehe auch #dict) |
In den meisten Programmiersprachen gibt es zum Ablegen von Werten sogenannte Variablen. Sie sind eine Art Schublade mit Namen darauf und können dann einen oder mehrere Werte enthalten, je nach Typ.
Vorlage unterscheidet zwar verschiedene Werte-Typen, aber eine Variable kann Werte beliebigen Typs aufnehmen, sie ist also nicht an einen Typ gebunden. Jede Variable ist durch einen Namen gekennzeichnet, bei dem Groß- und Kleinschreibung verschieden angesehen werden. Vorlage erkennt den Namen einer Variable an einem vorangestellten $ und kann so auch Variablennamen wie $REGION von dem gleichnamigen Objekt unterscheiden.
Eine typische Variable bekommt ihren Wert durch eine Zuweisung, wie diese Beispiele zeigen:
; Eine Integerzahl
$Holzmenge=5
; Eine Fließkommazahl
$Silbergewicht=0.1
; Ein String
$DummerSpruch='Andune ist nicht groß genug für uns beide, Babe!'
Eine neue Variable kann erzeugt werden, indem man ihr einfach etwas zuweist, d.h. sie entsteht dabei im Zweifelsfall einfach. In Ausdrücken hingegen kann man nur bereits existierende Variablen verwenden. Es wird also keine Variable durch das einfache Auslesen oder Ausgeben erzeugt. Dadurch bekommt man eine Fehlermeldung wenn man sich mal vertippt hat.
Alternativ kann man Variable mit den Befehlen #var, #array und #dict anlegen, was auch die einzige Möglichkeit ist, globale Variable anzulegen, die aus jeder Prozedur/Funktion sichtbar sind.
Globale Variable werden außerhalb von Prozeduren oder Funktionen in der Skript-Datei angelegt, lokale hingegen einfach in einer Funktion oder Prozedur. Sie werden nach Verlassen wieder gelöscht und es kann in verschiedenen Funktionen oder Prozeduren lokale Variablen mit gleichem Namen geben. Bei einem rekursiven Aufruf (eine Funktion oder Prozedur die sich selbst, hoffentlich nicht endlos ;-), benutzt) sieht man nicht den Wert aus dem voherigen Aufruf, sondern es exisiert für jeden Aufruf eine eigene Instanz.
Startet man Vorlage mit der Option -fd, so wird durch einfaches Zuweisen keine Variable mehr angelegt und statt dessen ein Fehler gemeldet. Man muß dann die Variable alle mit den oben genannten Befehlen erzeugen, was mehr Arbeit macht, aber einem weitere Sicherheit vor Tippfehlern bringt.
Die Inplace-Auswertung ist eine Art Makro-Mechanismus. Damit ist es möglich Ausdrücke, oder Teile davon, durch Skript-Befehle, als String zusammenzusetzen und später auszuwerten.
Ein Anwendungsbeispiel ist, eine Funktion zu schreiben, die nach Eingangsparametern eine bestimmte Region sucht und zurückgeben soll. Normalerweise ist das nicht möglich, weil eine Funktion ja nur einen Wert zurückgeben kann, aber eine Region durch zwei bis drei Koordinaten bestimmt ist. (Man könnte einen Index von REGION zurückgeben, aber das funktioniert nicht Rundenübergreifend oder ist u.U. nicht gewünscht.) Nun kann man statt dessen einfach einen Zugriff als String zurückgeben und diesen verwenden:
; FindeTolleRegion sucht nach der Region mit den meisten
; Rohstoffen eines gewuenschten Typs, und gibt einen String
; zurueck mit dem man über Inplace Zugriff auf die Region
; bekommen kann
#func FindeTolleRegion $Resource
{
$i=0 : $Max=0 : $iMax=0
#while $i<report.region.size
{
#if report.region[$i].$Resource>$Max
{
$iMax=$i
}
}
#return 'REGION['+report.region[$iMax].x+','\
+report.region[$iMax].y+','\
+report.region[$iMax].z+']'
}
Man kann hier auch sehen das man in Vorlage (ab Version 1.6rc3) lange Zeilen
umbrechen kann indem man einen Backslash verwendet. Geschieht dies, wie hier,
innerhalb eines Ausdrucks, so muß man darauf achten, das vor und nach dem Backslash
kein Leerzeichen kommt, damit der Ausdruck in der nächsten Zeile fortgesetzt
werden kann.
Verwendet wird das nun zum Beispiel so:
; Ausgeben der Region mit den meisten Bauern
$Reg=FindeTolleRegion('Bauern')
#message 'In '+$($Reg).name+' gibt es die meisten Bauern!'
ACHTUNG: Die Verwendung von Inplace-Ausdrücken ist zur Umgehung einiger noch existierender Mängel in der Metasprache (z.B. fehlende Referenzen) gedacht. Das Feature wird ab Version 2.0 mit ziemlicher Sicherheit ausgebaut. Eine eval()-Funktion wird einem aber die Möglichkeit geben, Ausdrücke aus Strings auszuwerten. Wer die jetzt schon will, kann sich mit dieser Lösung Portierungsaufwand verringern:
#func eval $expr
{
#return $($expr)
}
Revision 29 Jun 2006
|