YAML-Referenz¶
In diesem Kapitel erfährst du alle Details zur YAML-Datei, mit der du den Stift programmierst.
Das YAML-Format¶
Das YAML-Format im Allgemeinen wurde nicht für dieses Projekt erfunden, sondern ist gebräuchlich, um strukturierte Daten in einer menschenlesbaren Textdatei abzulegen. Eine knappe Übersicht findest du auf der Wikipedia-Seite zu YAML. Beachte, dass in YAML Einrückungen, also Leerzeichen am Anfang der Zeile, relevant sind und die Struktur der Datei beschreiben!
Die YAML-Datei bearbeitest du mit dem Texteditor deiner Wahl (Notepad, vim etc.).
YAML-Datei-Felder¶
Eine typische, minimale YAML-Datei für die Tiptoi-Programmierung sieht so aus:
product-id: 950
scripts:
8066:
- P(erstes_feld)
8067:
- P(zweites_feld)
Zwingend nötig ist dabei streng genommen nur das Feld product-id, aber in der Regel brauchst du auch scripts um irgendetwas Sinnvolles zu machen.
Es gibt noch eine Reihe weiterer, optionaler Felder, die im Folgenden erklärt werden. Eine etwas kompliziertere Datei könnte dann zum Beispiel so aussehen:
product-id: 950
comment: Ein kurzer Kommentar
welcome: willkommen
media-path: Audio/%s
gme-lang: GERMAN
init: $modus:=10
scripts:
haus:
- P(hello)
tuer:
- P(goodbye)
monster:
- P(warning)
language: en
speak:
hello: "Hello, friend!"
goodbye: "Goodbye"
warning: "Watch out."
scriptcodes:
haus: 4718
tuer: 4716
warning: 4717
product-id¶
- Format:
Ein OID-Code im Bereich 0 bis 999
- Beispiel:
product-id: 950
- Zweck:
Die Produkt-ID dieses Projekts. Das Anschaltfeld des Produktes sollte mit dem hier angegebenen OID-Code bedruckt sein.
Es sollte zu jeder Produkt-ID nur eine GME-Datei auf den Stift geladen werden. Ravensburger zählt seine Produkte fortlaufend ab 1 hoch und Sprachen werden mit 999 abwärts nummeriert. Wir raten dir für dein eigenes Projekt daher eine Zahl zwischen 900 und 950 zu wählen.
comment¶
- Format:
Ein Textstring
- Beispiel:
comment: "Mein Tiptoi-Produkt"
- Zweck:
Der Kommentar wird in der GME-Datei gespeichert, aber sonst ignoriert.
welcome¶
- Format:
Einen oder mehrere Audio-Dateinamen, durch Kommata getrennt
- Beispiel:
welcome: hello
- Zweck:
Beim Aktivieren des Produktes werden die angegebenen Audio-Dateien abgespielt.
media-path¶
- Format:
Ein Dateipfad, mit
%sals Platzhalter- Beispiel:
media-path: Audio/%s
- Zweck:
Gibt an, wo sich die Audiodateien befinden. Der Platzhalter
%swird dabei durch den in der YAML-Datei verwendeten Dateinamen ersetzt. Das Programm sucht nach allen geeigneten Dateiendungen (.wav,.ogg,.flac,.mp3).Beispiel: Für den im
welcome: helloangegebenen Begrüßungssound würde dastttoolalso die DateiAudio/hello.oggeinbinden.Beispiel 2: Wenn du
media-path: Audio/Schatzsuche_%sverwendest, würde bei einemwelcome: hellodie DateiAudio/Schatzsuche_hello.oggeingebunden werden.
gme-lang¶
- Format:
Eine Sprache (
GERMAN,ENGLISH,FRENCH…)- Beispiel:
gme-lang: GERMAN
- Zweck:
Das Sprach-Feld der GME-Datei. Bei eigenen Produkten gibt es in der Regel keinen Grund, dieses Feld anzugeben.
init¶
In diesem Feld werden Register (bzw. Variablen oder Speicherplätze) initialisiert. Beispielsweise werden hier Spielmodi oder Zähler auf 0 gesetzt, damit diese später mit einem vorgegebenen Wert starten können. Beispiel: Wird hier „$modus:=0 $i:=0“ geschrieben, so werden nach Aktivierung des Projekts die beiden Variablen modus und i mit 0 gestartet.
scripts¶
- Format:
Eine Zuordnung von OID-Codes (oder Code-Namen) zu einer Liste von Skriptzeilen.
- Beispiel:
scripts: 8067: - P(hi) haus: - $mode==3? P(welcome) - P(goodbye)
- Zweck:
Enthält die Logik dieses Tiptoi-Produktes und gibt für einen OID-Code an was geschehen soll, wenn du diesen Code antippst.
Statt eines konkreten OID-Codes kann auch ein Code-Name angegeben werden, siehe Abschnitt „scriptcodes“.
Die Skripte werden in Detail im Abschnitt „YAML-Programmierung“ erklärt.
timer¶
- Format:
Eine Liste von Skriptzeilen (wie ein Eintrag in
scripts)- Beispiel:
timer: - $countdown==1? $countdown:=0 CT P(explosion) - $countdown>1? $countdown-=1 P(tick)
- Zweck:
Das Timer-Skript. Der Stift verfügt über einen mit dem Befehl
ATstartbaren, periodischen Timer. Immer wenn dieser abläuft — und der Stift gerade nichts anderes tut — geht er die Zeilen des Timer-Skripts durch und führt die erste Zeile aus, deren Bedingungen erfüllt sind.
Zusammen mit den Befehlen AT (Timer starten) und CT (Timer abbrechen)
lassen sich damit verzögerte oder sich wiederholende Aktionen umsetzen, etwa
ein Countdown oder eine regelmäßige Erinnerung, wenn das Kind nichts mehr
antippt. Im obigen Beispiel würde ein normales Skript mit
$countdown:=10 AT(10) einen zehnsekündigen Countdown starten.
Das Timer-Skript teilt sich die Register mit den normalen Skripten. In den offiziellen Ravensburger-Produkten wird dieses Feld so gut wie nie verwendet.
language¶
- Format:
Ein Sprach-Kürzel (
de,en,fr…)- Beispiel:
language: de
- Zweck:
Gibt die Sprache für die Sprachsynthese (siehe Feld
speak) an.
speak¶
- Format:
Eine Zuordnung von Dateinamen zu Text
- Beispiel:
speak: hello: "Hello, friend!" goodbye: "Goodbye" warning: "Watch out."
- Zweck:
Gibt an, welche Audiodateien das
tttoolper Text-to-Speech generieren soll, sofern es die entsprechenden Audiodateien nicht findet. Dabei wird die inlanguageangegebene Sprache verwendet.
Das tttool verfügt über ein integriertes Text-to-Speech tool, welches dir erlaubt, Texte automatisch vorgelesen zu bekommen. So kannst du deine Tiptoi-Entwicklung testen, bevor du alles Nötige aufgenommen hast.
Solltest du Text-to-Speech in verschiedenen Sprachen benötigen, kannst du mehrere Abschnitte mit eigener Sprache angeben:
speak: - language: en hello: "Hello, friend!" goodbye: "Goodbye" - language: de warning: "Achtung!"
scriptcodes¶
- Format:
Eine Zuordnung von Codenamen zu OID-Code
- Beispiel:
scriptcodes: haus: 4718 tuer: 4716 warning: 4717
- Zweck:
Erlaubt dir, im Abschnitt
scriptsund inJ-Befehlen mit sprechenden Namen statt OID-Codes zu arbeiten. Bei der Erstellung der GME-Datei wird in dieser Zuordnung nachgeschlagen, welcher OID-Code verwendet werden soll.
Du kannst sprechende Namen auch ohne scriptcodes verwenden, in diesem Fall
wählt das tttool die Codes selbst. Damit stets die gleichen Codes verwendet
werden (und bereits gedruckte Codes weiterhin funktionieren), speichert es die
Auswahl in einer Datei mit Endung .codes.yaml, die nur den
scriptcodes-Eintrag enthält. Es steht dir frei, diese Zuordnung in die
eigentliche YAML-Datei zu übernehmen.
Warnung
Das tttool arbeitet entweder mit Namen oder mit Nummern. Du kannst
die beiden Varianten nicht mischen.
replay¶
- Format:
Ein OID-Code
- Beispiel:
replay: 12159
- Zweck:
Beim Tippen auf diesen Code wird das zuletzt ausgegebene Audio nochmal ausgegeben.
Auch wenn man diesen dies nicht explizit in der .yaml-Datei notiert, weist das tttool einen solchen Code zu, und erzeugt ein REPLAY-Muster aus.
stop¶
- Format:
Ein OID-Code
- Beispiel:
stop: 12158
- Zweck:
Beim Tippen auf diesen Code wird die Ausgabe gestoppt
Auch wenn man diesen dies nicht explizit in der .yaml-Datei notiert, weist das tttool einen solchen Code zu, und erzeugt ein STOP-Muster aus.
YAML-Programmierung¶
Die Logik einer Tiptoi-Programmierung steckt vor allem in den im scripts-Feld angegebenen Skripten. Es gibt zu jedem OID-Code ein Skript. Dieses besteht aus einer oder gegebenenfalls mehreren Zeilen, die wiederum aus Befehlen bestehen.
Das einfachste Beispiel ist also
scripts:
2000: P(hallo)
Hier wird, wenn du den OID-Code 2000 antippst, der Befehl P(hallo) ausgeführt. (Die Befehle selbst werden in Kürze erklärt.)
Eine Skriptzeile kann mehrere Befehle enthalten, etwa
scripts:
2000: P(hallo) P(freund) J(2001)
Hier werden drei Befehle nacheinander ausgeführt.
Warnung
Soweit bekannt kann es zu Problemen kommen, wenn mehr als 8 Befehle in einer Zeile stehen. Darüber hinaus interagieren manche Befehle seltsam; mehr dazu im Abschnitt „J – Sprung“.
Im Allgemeinen können zu einem Skript mehrere Zeilen angegeben werden:
scripts:
2000:
- $offen==1? P(willkommen)
- $offen==0? P(finde_den_schluessel)
Tippst du nun Code 2000 an, wird die erste Zeile ausgeführt, deren Bedingungen alle erfüllt sind (mehr zum Programmieren mit Bedingungen im Abschnitt zu Bedingungsbefehle).
Statt die OID-Codes numerisch anzugeben, kannst du auch sprechende Namen verwenden, siehe Abschnitt „scriptcodes“.
Register¶
Viele Befehle manipulieren Register. Diese repräsentieren Speicherzellen, in denen im Programmverlauf Werte abgelegt und abgerufen werden können. Man könnte sie auch Variablen nennen.
Der Name eines Registers beginnt immer mit einem $, gefolgt von Buchstaben, Zahlen oder Unterstrichen (_). Direkt nach dem $ muss ein Buchstabe kommen.
Alle Arithmetik auf dem Tiptoistift arbeitet mit ganzen Zahlen im Bereich 0 bis 65535. Alle Register haben zu Beginn den Wert 0, sofern du es nicht im init-Feld anders verlangst (siehe Abschnitt „init“).
Wenn du eine GME-Datei exportierst (siehe Abschnitt „GME-Dateien extrahieren“), so kennt das tttool die Namen der Register nicht. In diesem Fall werden Nummern verwendet ($0, $1…). Es gibt in der Regel keinen Grund, dies in deinen eigenen Tiptoi-Produkten so zu machen.
Befehlsreferenz¶
Im Folgenden werden die Befehle im Einzelnen erklärt: Wie du sie in der YAML-Datei schreibst, was sie bewirken, und was sonst so dabei zu beachten ist.
In der Format-Beschreibung werden folgende Platzhalter verwendet:
audio-datei: Der Name einer Audio-Datei. Aus dem Namen wird, wie im Abschnitt „media-path“ beschrieben, der Dateiname der Audiodatei abgeleitet.
oid-code: Die Nummer eines OID-Codes (und damit einer Skiptzeile), wenn
scriptcodesnicht verwendet wird.code-name: Der Name eines OID-Codes (und damit einer Skiptzeile), wenn
scriptcodesverwendet wird.register: Der Name eines Registers, mit $. Beispiel: $mode.
argument: Entweder der Name eines Registers oder eine Zahl. Beispiele: $mode, 0, 1024.
Der Wert eines Argumentes ist im ersten Fall der aktuell in dem Register gespeicherte Wert; im zweiten Fall einfach die Zahl selbst.
P – Audio abspielen¶
- Format:
- P(audio-datei)P(audio-datei,audio-datei,…)
- Beispiel:
haus: - P(willkommen) P(zu_hause,daheim)
- Effekt:
In der ersten Form spielt der Befehl die angegebene Audio-Datei ab.
In der zweiten Form spielt der Befehl zufällig eine der angegebenen Audio-Dateien ab.
- Hinweis:
Wenn der Dateiname Zeichen enthält außer a-z, 0-9 und _, dann muss der Dateiname in Anführungszeichen stehen.
- Beispiel:
haus: - P("Willkommen zu Hause")
P? – Audio vielleicht abspielen¶
- Format:
- P?(audio-datei)
- Beispiel:
truhe: - P(knarzen) P?(ueberraschung)
- Effekt:
Der Befehl spielt die angegebene Audio-Datei ab — aber nur ungefähr jedes zweite Mal, zufällig; sonst tut er nichts.
Der Stift wirft dabei keine echte Münze: Er schaut, ob ein interner Zähler,
der etwa zehnmal pro Sekunde und bei jeder Interaktion weiterzählt, gerade
eine gerade Zahl enthält. In der Praxis ist das Ergebnis damit zufällig, mit
einer Wahrscheinlichkeit von etwa 50%. Für andere Wahrscheinlichkeiten
kombiniere T (siehe Abschnitt Zufallszahlen) mit Bedingungen.
J – Sprung¶
- Format:
- J(oid-code)J(code-name)
- Beispiel:
endlos: - P(endlose) P(kein_anschluss)
- Effekt:
Der Stift führt, nach dem aktuellen Skript, das Skript mit Code oid-code bzw. code-name (wenn scriptcodes verwendet wird) aus.
Es sollte nur ein J-Befehl pro Zeile existieren (bei mehreren wird der letzte ausgeführt).
Nach dem J-Befehl sollte mindests ein P-Befehl stehen, der ein nicht zu kurzes Audio-Schnippsel (mindestens 5ms) abspielt, sonst warten Tiptoi-Stifte (ab der zweiten Generation) beim Sprung etwa zwei Sekunden lang.
Eine stille, 5ms lange Audiodatei liegt dem tttool als example/5ms.ogg bei.
Bemerkung
Messungen mit der emulierten Stift-Firmware (ZC3202N, tt-emu)
präzisieren das Verhalten: Der Stift merkt sich den Sprung nur vor und
führt ihn erst aus, wenn das gerade laufende Audio zu Ende ist. Die
bekannte Verzögerung beim Verketten von Skripten ist genau dieses Warten —
das Audio des Sprungziels beginnt erst, wenn das der aktuellen Zeile fertig
ist. Die Reihenfolge von J und P innerhalb der Zeile ist dabei
egal (P(lang) J(ziel) und J(ziel) P(lang) verhalten sich
identisch; die Playlist der Zeile spielt vor dem Sprung). Ein J ganz
ohne laufendes Audio sprang in der Emulation dagegen sofort — die oben
erwähnte Zwei-Sekunden-Wartezeit ließ sich dort nicht reproduzieren.
Details und Messwerte: testsuite/emulator-tests/test_jump.py.
:= – Register setzen¶
- Format:
- register1 := argument
- Beispiel:
- $zuletzt := $aktuell $aktuell := 5
- Effekt:
Der Wert des Registers register wird auf den Wert des Arguments argument gesetzt.
+=, -=, *=, /=, %= – Arithmetik¶
- Format:
- register += argumentregister -= argumentregister *= argumentregister /= argumentregister %= argument
- Beispiel:
taste_fuenf: - $anzeige*=10 $anzeige+=5 gegner_getroffen - $wert := 10 $wert *= $bonus $score += $wert
- Effekt:
Es wird die entsprechende Rechenoperation auf die aktuell in register gespeicherte Zahl und den Wert des Arguments argument angewandt, und das Ergebnis in register1 abgelegt.
Es wird dabei nur mit ganzen Zahlen gerechnet. Insbesondere rundet die Division (/=) das Ergebnis stets ab. Wenn also Register $x den Wert 8 enthält und $x/=3 ausgeführt wird, so enthält es den Wert 2.
Der Befehl %= berechnet entsprechend den Divisionsrest. Wenn also Register $x den Wert 8 enthält und $x%=3 ausgeführt wird, so enthält es den Wert 2.
Neg() – Register negieren¶
- Format:
- Neg(register)
- Beispiel:
- Neg($r)
- Effekt:
Der Wert des Registers register wird negiert: Aus 5 wird -5 und umgekehrt.
&=, |=, ^= – bitweise Operatoren¶
- Format:
- register &= argumentregister |= argumentregister ^= argument
- Zweck:
Es wird die entsprechende bitweise Operation auf die aktuell in register gespeicherte Zahl und den Wert des Arguments argument angewandt, und das Ergebnis in register abgelegt.
Dabei ist &= das bitweise Und, |= das bitweise Oder, ^= das bitweise exklusive Oder (XOR). Wenn dir das nichts sagt, brauchst du es vermutlich nicht.
T – Timer¶
- Format:
- T(register,modulus )
- Beispiel:
wuerfel: - T($wurf,6)
- Effekt:
Der Wert des Tiptoi-Zählers zu Beginn des Skriptes wird (modulo dem modulus) im Register register abgelegt.
Der Tiptoi-Stift verfügt über einen Zähler, der während der Benutzung hochgezählt wird. Er wird schneller hochgezählt, wenn mit dem Stift interagiert wird, er ist also nicht zur Zeitmessung geeignet. Man kann damit aber (einfache) Zufallszahlen bekommen. Mehr dazu im Abschnitt Zufallszahlen. (Zur Zeitmessung dient stattdessen der mit AT gestartete Timer.)
AT, CT – Timer starten und abbrechen¶
- Format:
- AT(periode)CT
- Beispiel:
scripts: bombe: - $countdown:=10 AT(10) P(zischen)
- Effekt:
ATstartet den periodischen Timer des Stiftes: Alle periode × 100 Millisekunden — im Beispiel also jede Sekunde — führt der Stift, sofern er gerade nichts anderes tut, das Timer-Skript aus (siehe Feld „timer“). Ein erneutesATersetzt den laufenden Timer;CTbricht ihn ab.
Die periode wird immer als Zahl interpretiert; ein Register (etwa
AT($p)) ist hier nicht möglich. Der Timer läuft, bis er mit CT
abgebrochen wird, ein neues AT ihn ersetzt oder der Stift das Produkt
verlässt.
==, >=, <=, >, <, != – Bedingungen¶
- Format:
- argument1 == argument2argument1 >= argument2argument1 <= argument2argument1 > argument2argument1 < argument2argument1 != argument2
- Beispiel:
haus: - $mode == 1? P(willkommen) - $mode == 2? $gefunden < 3? P(finde_mehr_steine) - $mode == 2? $gefunden == 3? P(raetsel_geloest)
- Effekt:
Bedingungsbefehle müssen stets am Anfang der Zeile stehen. Es wird der Wert des ersten Arguments entsprechend dem Vergleichsoperator mit dem zweiten Argument verglichen. Wenn alle Bedingungsbefehle einer Zeile zutreffen, dann wird die Zeile ausgeführt, sonst wird die nächste Zeile des Skriptes geprüft.
Die Operatoren sind:
Befehl
Bedeutung
==
gleich
>=
größer oder gleich
<=
kleiner oder gleich
>
echt größer
<
echt kleiner
!=
ungleich
Weitere Befehle¶
(Befehle die der normale Tiptoi-Bastler nicht braucht, aber die das tttool ausspuckt)
P*(…): Spielt eine der Audio-Dateien der Zeile ab, praktisch zufällig. Anders als beimP-Befehl mit mehreren Argumenten wählt der Stift dabei aus allen Audio-Dateien der Zeile aus, auch aus denen der anderenP-Befehle derselben Zeile.PA*(…): Spielt alle Audio-Dateien der Zeile ab, eine nach der anderen — auch hier: alle Dateien der gesamten Zeile.PA(…): Spielt die angegebenen Audio-Dateien ab, eine nach der anderen.G(…): Startet ein Spiel der GME-Datei. Spiele sind in der GME-Datei gespeicherte, von der Stift-Firmware ausgeführte Abläufe; sie werden imgames-Feld der YAML-Datei definiert (das in diesem Buch bislang nicht weiter beschrieben ist;tttool gameszeigt die Spiele einer GME-Datei an).C: Bricht ein laufendes Spiel ab.?(…) (…): So gibt dastttooleinen Befehl aus, den es nicht kennt, zusammen mit seinen rohen Bytes.