--------- Fortsetzung -----------------------
Das Ganze ist im Prinzip lediglich eine Makro-Sammlung, die unter dem Makroprozessor
"M4" lauffähig ist. Die Nutzung eines Makroprozessors mit naturgemäss eingeschränktem Funktionsumfang für einen solchen Zweck gilt gemeinhin als eine weniger elegante und zuverlässige Lösung als zB die Entwicklung einer dem Problem bestmöglich angepassten Speziallösung, am besten in einer weitverbreiteten und leistungsfähigen Hochsprache (zB C/C++), aber die technisch simplere Lösung erzwingt auch die Konzentration auf das Wesentliche. Ein Fakt der häufig übersehen wird.
Ein zentrales Problem bei einer Compilerlösung war zB immer die Umsetzung der nfo-Spritenummern in eine vom Compiler verwaltete Befehlskette. In meinem Ansatz habe ich davon ganz abgesehen (weil technisch nicht machbar) und die Definition und Referenzierung der .nfo Sprite-Nummern einfach manuell belassen. Dies hat durchaus Vorteile, denn der neue Code ist dadurch wesentlich lesbarer als wenn man zB eine Lisp-artige Schachtelung der Befehlsketten implementieren würde. Zudem ist die eigenständige Verwaltung (Neuvergabe, Wiederbenutzung) von Sprite-Nummern durch einen Compiler auch nicht gerade einfach zu implementieren und ohne explizite Sprite-Nummern würde man ein zusätzliches Debugging-Tool benötigen, etc ..., und eine Makro-Bibliothek ist leicht erweiterbar und veränderbar, im Gegensatz zu einem Compiler.
Die Definition von Sprite-Nummern (c-IDs) und ihre Referenzierung habe ich sinnvollerweise in zwei verschiedene Funktionen getrennt:
def(<n>) definiert eine Sprite-Nummer,
ref(<n>) referenziert eine Sprite-Nummer.
Die in nfo vorhandenen "properties" können nun ganz einfach durch einen Katalog von Funktionen abgebildet werden. Abgesehen von einer besseren Lesbarkeit des Codes kann man zusätzlich eine gewisse "Automatisierung" durch die Art und Weise ihrer Implementierung erreichen.
ZB sind in einem grossen Fahrzeugset Ketten aus "varaction2" mit schätzungsweise 90% der Codezeilen, bzw Spritenummern beteiligt. Kern einer varaction2 ist (in nfo Syntax) ein Konstrukt dass in etwa einem "C" switch/case Block entspricht.
Dies habe ich auch entsprechend so implementiert, nur dass eben das zentrale Konstrukt eines solchen Blocks, das neue "if" Statement, sehr flexibel implementiert ist und dadurch, wie oben beschrieben, dem Programmierer überflüssige Arbeit ersparen hilft.
Sehen wir uns dies einmal genauer an.
1. Syntax für varaction2
1.1 Das "if" Statement
if(<Ganzzahl Konstante> | <Bereich> | <Liste>)
Das "if" Statement vereinfacht den nfo "switch/case" Block.
ZB kann der nfo-Block
Code:
-1 * 0 00 02 00 81 40 00 03 03
03 00 03 03
02 00 02 02
01 00 01 01
00 00
nun einfach als
Code:
def(0) vehpos(MOD4,
ref(3) if(3)
ref(2) if(2)
ref(1) if(1)
ref(0) else
)
geschrieben werden. Hier zeigt sich deutlich die Trennung zwischen der Referenz einer c-ID und der Auswertung der "property" auf dem die erfolgende Referenz beruht.
Die Idee lässt sich verbessern:
Aus
Code:
-1 * 0 00 02 00 81 10 00 FF 01
62 80 01 03
FF 80
wird
Code:
def(0) articulated(
addveh(0x62) if(1 .. 3)
ENDLIST else
)
Das "if" Statement kennt als Parameter auch einen Bereich, genauso wie nfo das auch implementiert. Hier sieht man ausserdem, dass sich recht einfach Konstanten per Textersatz lesbarer gestalten lassen, wie zB das "FF 80" am Ende einer Liste von artikulierten Teilfahrzeugen oder am Ende einer Liste von "text suffixes".
Das "if" ist aber noch nicht am Ende, es kennt auch Listen als Parameter:
Aus dem nfo-Block
Code:
-1 * 0 00 02 00 81 B9 00 FF 03
FE 80 00 00
FE 80 02 02
FE 80 0A 0A
20 80
wird
Code:
def(0) cargo(
ATT_OK if(PASS, MAIL, VALU)
ATT_VAN else
)
D.h. wenn verschiedenen Ergebniswerten ein und dieselbe Referenz zugeordnet werden soll, müssen diese Werte nicht einzeln aufgeführt werden wie zB hier:
Code:
def(0) cargo(
ATT_OK if(PASS)
ATT_OK if(MAIL)
ATT_OK if(VALU)
ATT_VAN else
)
sondern das "if" Statement ermöglicht eine kompaktere Notation als die einer 1:1 Abbildung auf die nfo. Auch hier sind die "ATT_*" übrigens wieder (frei vereinbare) Konstanten, die zB Referenzen oder Callback-Resultate sein können. Hier sind es Resultate für den callback 1D ("wagon attach"), die angeben ob ein bestimmtes Fahrzeug angehängt werden kann ("ATT_OK") oder nicht ("ATT_VAN": "Güterwagen kann nicht angehängt werden").
--------- Ende Teil 2 -----------------------
Gruß
Michael