Du programmierst ein Spiel, das man anrufen kann: Es spricht mit einer echten Stimme, spielt Musik und hört auf die Tasten des Telefons. Erst begrüßt dich dein Programm, dann stellt es eine Frage, und am Ende führt es durch eine Höhle, in der es flüstert, still wird und Musik spielt, wenn man den Schatz findet. Zum Schluss schreibst du deine eigene Geschichte: Jemand aus deiner Klasse spielt sie durch, und im Telefonbuch kann sie jeder anrufen.
»Drücken Sie die 1 für den Kundendienst, die 2 für …«: So ein Telefon, das spricht und auf Tasten hört, ist ein Programm. Es sagt etwas, wartet auf eine Taste und macht je nach Taste anders weiter. Genau so ein Programm schreibst du. Wer anruft, sieht nichts davon: Alles, was dein Spiel zu bieten hat, ist zu hören.
Im Workspace probierst du dein Spiel mit dem Befehl telefon aus. Er startet
dein Programm und zeigt dir im Browser ein Telefon mit Tastenfeld. Daneben
steht, was das Spiel sagt, Wort für Wort, während du es hörst.
Fertige Spiele kommen ins Telefonbuch. Dort ruft man sie im Browser an, auch ohne Workspace: die Nummer eintippen und auf den grünen Hörer drücken. Steht dort schon ein Spiel, ruf es an, bevor du anfängst, und hör genau hin: Was davon könntest du selbst programmieren?
Eine echte Telefonnummer gibt es noch nicht. Wir arbeiten daran, dass man die Spiele auch mit einem Telefon anrufen kann.
Lege im Terminal (StrgJ) einen Ordner an und öffne ihn mit StrgK StrgO:
mkdir /workspace/telefon
Lege darin die Datei hallo.rb an:
require 'telefon' say 'Hallo! Hier spricht dein erstes Telefonspiel.'
require 'telefon' lädt die Befehle des Telefons, und say sagt einen Text.
Ruby wartet, bis der Satz gesprochen ist, und macht erst dann mit der nächsten
Zeile weiter.
Lege darin die Datei hallo.py an:
from telefon import say say('Hallo! Hier spricht dein erstes Telefonspiel.')
Die erste Zeile holt den Befehl say aus der Bibliothek des Telefons, und
say sagt einen Text. Python wartet, bis der Satz gesprochen ist, und macht
erst dann mit der nächsten Zeile weiter.
Lege darin die Datei hallo.js an:
const { say } = require('telefon'); say('Hallo! Hier spricht dein erstes Telefonspiel.');
Die erste Zeile holt den Befehl say aus der Bibliothek des Telefons, und
say sagt einen Text. JavaScript wartet, bis der Satz gesprochen ist, und
macht erst dann mit der nächsten Zeile weiter.
Starte das Telefon im Terminal, im Ordner telefon:
telefon hallo.rb
telefon hallo.py
telefon hallo.js
Das Terminal nennt eine Adresse; sie steht auch im Reiter »Ports« neben »Terminal«, bei Port 8040. Öffne sie im Browser und klick auf den grünen Hörer. Jetzt startet dein Programm, und du hörst seine Stimme: Es spricht Thorsten. Im Terminal steht jeder Satz in dem Moment, in dem er gesprochen wird.
Nach der letzten Zeile ist das Programm zu Ende, und damit auch der Anruf. Ein
Klick auf den Hörer ruft noch einmal an: Das Programm startet dann von vorn.
Hast du die Datei geändert, hörst du beim nächsten Anruf die neue Fassung;
telefon selbst musst du dafür nicht neu starten. Beenden kannst du es im
Terminal mit StrgC.
Dein erstes Telefonspiel in telefon/hallo.rb sagt etwas, wenn man anruft.
Dein erstes Telefonspiel in telefon/hallo.py sagt etwas, wenn man anruft.
Dein erstes Telefonspiel in telefon/hallo.js sagt etwas, wenn man anruft.
say und ruf noch einmal an. Achte darauf, wann der zweite
Satz beginnt: Steht er schon da, während der erste noch gesprochen wird?
Thorsten Müller aus dem Wetteraukreis bei Frankfurt am Main wollte einen Sprachassistenten bauen, der ohne Cloud auskommt: Ihm war nicht wohl bei dem Gedanken, dass ein Mikrofon zu Hause Sprachaufnahmen an fremde Server schickt. Eine freie deutsche Stimme dafür gab es nicht. Also nahm er ab 2019 abends und an Wochenenden Satz für Satz seine eigene Stimme auf, zusammen mit Dominik Kreutz, der die Aufnahmen bearbeitete. Über die Jahre wurden es mehr als 30 000 Aufnahmen, zusammen über 40 Stunden.
Er hat seine Stimme verschenkt: Die Aufnahmen stehen unter CC0, alle dürfen damit eine Stimme trainieren. Aus ihnen ist die Stimme gemacht, die in deinem Telefonspiel spricht, auch die Stimmungen: Dafür hat er 300 Sätze in jeder Stimmung aufgenommen.
Foto: Thorsten Müller, 2025, CC BY 4.0, zugeschnitten (Wikimedia Commons)
Ein Spiel am Telefon lebt von dem, was man hört. Mit music spielt dein
Programm Musik, und mit einer Pause davor hört man sie erst eine Weile allein,
bevor die Stimme einsetzt:
require 'telefon'music 'https://www.youtube.com/watch?v=-xRD8VmjBQM'sleep 3say 'Hallo! Hier spricht dein erstes Telefonspiel.'
from telefon import music, say, sleepmusic('https://www.youtube.com/watch?v=-xRD8VmjBQM')sleep(3)say('Hallo! Hier spricht dein erstes Telefonspiel.')
In der ersten Zeile stehen jetzt auch music und sleep, die anderen
beiden Befehle, die dein Programm aus der Bibliothek braucht.
const { music, say, sleep } = require('telefon');music('https://www.youtube.com/watch?v=-xRD8VmjBQM');sleep(3);say('Hallo! Hier spricht dein erstes Telefonspiel.');
In der ersten Zeile stehen jetzt auch music und sleep, die anderen
beiden Befehle, die dein Programm aus der Bibliothek braucht.
Von einem Video nimmt das Telefon nur den Ton, und es spielt ihn in einer
Schleife, bis dein Programm zu Ende ist. music wartet, bis die Musik läuft.
Das Video holt telefon schon, sobald es gestartet ist, und es bereitet auch
die Sätze deines Spiels vor; im Terminal steht, wann beides bereit ist. Rufst
du gleich nach dem Start an, dauert der erste Anruf darum etwas länger. Statt
eines Links nimmt music auch eine Datei; dazu gleich mehr.
Brauchst du nur eine Stelle aus einem längeren Video, sag, wo sie anfängt
und wo sie aufhört: music '…', start: '1:15', stop: '1:52' spielt die
Musik von Minute 1:15 bis 1:52 und dann wieder ab 1:15. Ohne stop geht es
ab start weiter. Kopierst du bei YouTube mit »Teilen« einen Link ab einer
Stelle, endet er auf t=75; auch dann beginnt die Musik dort.
Brauchst du nur eine Stelle aus einem längeren Video, sag, wo sie anfängt
und wo sie aufhört: music('…', start='1:15', stop='1:52') spielt die
Musik von Minute 1:15 bis 1:52 und dann wieder ab 1:15. Ohne stop geht es
ab start weiter. Kopierst du bei YouTube mit »Teilen« einen Link ab einer
Stelle, endet er auf t=75; auch dann beginnt die Musik dort.
Brauchst du nur eine Stelle aus einem längeren Video, sag, wo sie anfängt
und wo sie aufhört: music('…', { start: '1:15', stop: '1:52' }) spielt die
Musik von Minute 1:15 bis 1:52 und dann wieder ab 1:15. Ohne stop geht es
ab start weiter. Kopierst du bei YouTube mit »Teilen« einen Link ab einer
Stelle, endet er auf t=75; auch dann beginnt die Musik dort.
sleep wartet, so viele Sekunden, wie du angibst. Die Musik spielt dabei
weiter.
telefon/hallo.rb spielt Musik und sagt danach etwas.
Die Zeile mit music steht vor dem say, mit einem Link oder dem Namen einer Datei in Anführungszeichen.
telefon/hallo.py spielt Musik und sagt danach etwas.
Die Zeile mit music('…') steht vor dem say, und in der ersten Zeile holt from telefon import auch music.
telefon/hallo.js spielt Musik und sagt danach etwas.
Die Zeile mit music('…'); steht vor dem say, und in der ersten Zeile holt require('telefon') auch music.
Hör genau hin, wenn die Stimme einsetzt: Die Musik wird leiser, solange ein Satz gesprochen wird, und danach wieder laut. So macht es auch das Radio, wenn jemand über die Musik spricht. Dein Programm muss dafür nichts tun.
0 und 1, in Ruby mit
music '…', volume: 0.3, in Python und JavaScript mit
music('…', 0.3). Ohne Angabe spielt sie mit 1, so
laut wie möglich. Achte darauf, ob du die Stimme bei 1 noch gut
verstehst.
Statt eines Links nimmt music auch eine Datei. Sie muss direkt im Ordner
telefon liegen, neben deinem Spiel; dann schreibst du nur ihren Namen. Ein
Stück für die Höhle, das wir selbst gemacht haben, holst du im Terminal in
deinen Ordner:
wget https://workspace.hackschule.de/telefonspiel/hoehle.mp3
hallo.rb den Link durch den Namen der
Datei, music 'hoehle.mp3', und ruf an. Achte darauf, ob die Musik nach dem
Satz weiterläuft und ob du hörst, wo sie wieder von vorn beginnt.
hallo.py den Link durch den Namen der
Datei, music('hoehle.mp3'), und ruf an. Achte darauf, ob die Musik nach dem
Satz weiterläuft und ob du hörst, wo sie wieder von vorn beginnt.
hallo.js den Link durch den Namen der
Datei, music('hoehle.mp3');, und ruf an. Achte darauf, ob die Musik nach dem
Satz weiterläuft und ob du hörst, wo sie wieder von vorn beginnt.
Eigene Musik oder ein Geräusch ziehst du aus dem Dateimanager deines
Computers in VS Code auf den Ordner telefon. Das Telefon spielt vier
Formate, an der Endung der Datei zu erkennen:
| Format | Endung | |
|---|---|---|
| MP3 | .mp3 |
klein, und jeder Browser spielt es: Nimm MP3, wenn du die Wahl hast. |
| WAV | .wav |
jeder Browser spielt es, aber die Datei ist groß; warum, steht im nächsten Abschnitt. |
| Ogg | .ogg |
klein; das Telefon spielt es, im Workspace nicht jeder Browser. |
| M4A | .m4a |
so speichern viele Handys Aufnahmen; das Telefon spielt es, im Workspace nicht jeder Browser. |
Eine Datei in einem anderen Format oder in einem Unterordner nimmt music
nicht an: Sie käme beim Veröffentlichen nicht mit ins Telefonbuch. Dorthin
kommt auch nur, was höchstens 20 MB groß ist, alle Dateien zusammen
höchstens 40 MB. Hörst du im Workspace nichts, öffne die Datei in
Audacity und exportiere sie als MP3. Dieselben
Regeln gelten für eigene Aufnahmen, die
mit play statt Thorsten sprechen.
Ton ist schwingende Luft: Der Luftdruck steigt und fällt, viele Male in der Sekunde, und dein Trommelfell schwingt mit. Ein Mikrofon macht daraus eine elektrische Spannung, die genauso steigt und fällt. Der Computer misst diese Spannung in gleichen Abständen und speichert jede Messung als Zahl. Das heißt Abtasten, auf Englisch Sampling; jede Messung ist ein Sample, und wie oft in der Sekunde gemessen wird, ist die Abtastrate (Sample Rate), angegeben in Hertz (Hz).
Was zwischen zwei Messungen geschieht, weiß der Computer nicht. Eine Schwingung bleibt nur erhalten, wenn er sie mehr als zweimal pro Schwingung misst: Mit 8.000 Messungen in der Sekunde kommen Töne bis 4.000 Hz an, alles Höhere fehlt. Der tiefe Ton der Höhlenmusik schwingt 55-mal in der Sekunde, also mit 55 Hz; das Zischen eines »s« liegt zum großen Teil über 4.000 Hz.
Das Telefonspiel rechnet mit 16.000 Messungen in der Sekunde, so kommen Thorsten und die Musik beim Telefon an. Das alte Telefonnetz übertrug nur 8.000; am Telefon buchstabiert man darum mit Wörtern, »S wie Samuel«, weil »s« und »f« dort ähnlich klingen. Eine CD misst 44.100-mal in der Sekunde, etwas mehr als doppelt so oft wie die höchsten Töne, die Menschen hören, um 20.000 Hz.
Jede Messung ist eine Zahl, auf einer CD 2 Byte groß, und eine WAV-Datei
speichert jede einzeln: In einer Sekunde Ton mit 44.100 Hz stecken 88.200
Byte, für zwei Lautsprecher doppelt so viel. hoehle.mp3 dauert 48 Sekunden
und ist 0,6 MB groß; als WAV wären es 4,2 MB. MP3 lässt weg, was man kaum
hört, und speichert den Rest geschickter.
Claude Shannon (1916–2001). Wie viele Bits eine Nachricht mindestens braucht, rechnete er 1948 aus und gründete damit die Informationstheorie; das Wort Bit machte er bekannt. Er fuhr Einrad, jonglierte und baute die Maus Theseus, die selbst lernte, durch ein Labyrinth zu finden.
Schon als Student am MIT zeigte er 1937 in seiner Masterarbeit, dass sich Schaltungen aus Relais mit der Algebra von George Boole beschreiben und vereinfachen lassen, mit 1 und 0 für einen Kontakt, der geschlossen oder offen ist. Damit begann die Theorie der digitalen Schaltungen.
Einen Code mit so wenigen Bits wie möglich suchten er und Robert Fano fast gleichzeitig, jeder für sich. Der Shannon-Fano-Code kam nah heran, aber nicht immer ganz.
In derselben Arbeit von 1948 ließ er englische Texte Wort für Wort entstehen, jedes Wort nach dem vorigen aus einem Buch gezogen: ein winziges Sprachmodell, von Hand.
1949 bewies er einen Satz, den Nachrichtentechniker schon kannten: Schwingt ein Signal höchstens W-mal in der Sekunde, ist es ganz festgehalten, wenn man es 2W-mal in der Sekunde misst. Nach diesem Abtasttheorem richtet sich, wie oft ein Computer Ton misst.
Foto: Tekniska museet, CC BY 2.0, zugeschnitten (Wikimedia Commons)
Früher lief ein Anruf als elektrische Schwingung durch Kupferdrähte, und Vermittlungsstellen schalteten für jedes Gespräch eine Leitung von einem Telefon zum anderen durch. Fachleute nennen dieses alte Netz POTS, »plain old telephone service«. Heute geht fast jeder Anruf als Datenpakete durch das Internet, Voice over IP: Der Router zu Hause oder das Handy macht aus der Stimme Zahlen und schickt sie in kleinen Paketen los, eines alle 20 Millisekunden. In Deutschland hat die Telekom bis Ende 2020 alle ihre Anschlüsse so umgestellt, Großbritannien schaltet sein altes Netz Ende Januar 2027 ab.
So wird auch die Telefonnummer des Telefonspiels angeschlossen, an der wir arbeiten: Ein Anruf kommt über das Protokoll SIP bei einem Server an, auf dem Asterisk ihn annimmt, und Thorstens Stimme geht in Paketen zurück, 16.000 Zahlen in der Sekunde.
Jetzt soll dein Spiel zuhören. Lege eine neue Datei an:
frage.rb:
require 'telefon' say 'Katzen oder Hunde? Drück 1 für Katzen, 2 für Hunde.' key = keys(1) if key == '1' say 'Miau! Katzen schlafen bis zu sechzehn Stunden am Tag.' elsif key == '2' say 'Wuff! Hunde hören Töne, die für dich zu hoch sind.' else say 'Du hast nichts gedrückt. Schade!' end
frage.py:
from telefon import keys, say say('Katzen oder Hunde? Drück 1 für Katzen, 2 für Hunde.') key = keys(1) if key == '1': say('Miau! Katzen schlafen bis zu sechzehn Stunden am Tag.') elif key == '2': say('Wuff! Hunde hören Töne, die für dich zu hoch sind.') else: say('Du hast nichts gedrückt. Schade!')
frage.js:
const { keys, say } = require('telefon'); say('Katzen oder Hunde? Drück 1 für Katzen, 2 für Hunde.'); const key = keys(1); if (key === '1') { say('Miau! Katzen schlafen bis zu sechzehn Stunden am Tag.'); } else if (key === '2') { say('Wuff! Hunde hören Töne, die für dich zu hoch sind.'); } else { say('Du hast nichts gedrückt. Schade!'); }
keys(1) wartet auf eine Taste und gibt sie zurück, als Text: '1', wenn
jemand die 1 drückt. Drückt zehn Sekunden lang niemand etwas, gibt keys
einen leeren Text zurück, ''. Danach entscheidet die Verzweigung, was das
Spiel sagt. Starte das Telefon mit der neuen Datei und probier alle drei Wege
aus: die 1, die 2 und gar keine Taste.
Eine Taste, die jemand drückt, während das Spiel noch spricht, geht nicht
verloren: Sie wartet, bis dein Programm keys aufruft. Wer die Frage schon
kennt, muss sie also nicht bis zum Ende anhören.
Auf dem Telefon steht eine 1, und keys gibt '1' zurück, mit
Anführungszeichen. Ist das nicht dasselbe?
Jemand ändert in frage.rb die Zeile if key == '1' in if key == 1, ohne Anführungszeichen. Was sagt das Spiel, wenn man die 1 drückt?
Jemand ändert in frage.py die Zeile if key == '1': in if key == 1:, ohne Anführungszeichen. Was sagt das Spiel, wenn man die 1 drückt?
Jemand ändert in frage.js die Zeile if (key === '1') { in if (key === 1) {, ohne Anführungszeichen. Was sagt das Spiel, wenn man die 1 drückt?
Hier geht es weiter, sobald du deine Antwort oben abgegeben hast.
Das Spiel sagt »Du hast nichts gedrückt. Schade!« Denn keys gibt einen Text
zurück, auch wenn er nur aus einer Ziffer besteht, und ein Text ist nie
gleich einer Zahl: '1' == 1 ist falsch.
Das Spiel sagt »Du hast nichts gedrückt. Schade!« Denn keys gibt einen Text
zurück, auch wenn er nur aus einer Ziffer besteht, und ein Text ist nie
gleich einer Zahl: '1' == 1 ist falsch.
Das Spiel sagt »Du hast nichts gedrückt. Schade!« Denn keys gibt einen Text
zurück, auch wenn er nur aus einer Ziffer besteht, und === prüft auch, ob
beides von derselben Art ist: '1' === 1 ist falsch. Mit == wäre es wahr,
weil JavaScript den Text dann erst in eine Zahl verwandelt; darum vergleicht
man in JavaScript mit ===.
Darum vergleicht dein Programm mit '1' in Anführungszeichen. So kann keys
auch den Stern '*' zurückgeben, und mehrere Tasten auf einmal, wie '472'.
Nur die Raute # gibt keys nie zurück: Sie beendet eine Eingabe aus
mehreren Tasten.
Jede Antwort ist ein eigener Zweig der Verzweigung. Für die 3 kommt ein weiterer dazu, vor dem Zweig für »nichts gedrückt«: Der fängt alles auf, was die Zweige davor nicht erkannt haben.
Ein neuer Zweig zwischen dem für die 2 und else:
elsif key == '…' say '…'
Ein neuer Zweig zwischen dem für die 2 und else::
elif key == '…': say('…')
Ein neuer Zweig zwischen dem für die 2 und else:
} else if (key === '…') { say('…');
require 'telefon'say 'Katzen, Hunde oder Fische? Drück 1 für Katzen, 2 für Hunde, 3 für Fische.'key = keys(1)…elsif key == '2' say 'Wuff! Hunde hören Töne, die für dich zu hoch sind.'elsif key == '3' say 'Blubb! Fische haben keine Augenlider.'else
from telefon import keys, saysay('Katzen, Hunde oder Fische? Drück 1 für Katzen, 2 für Hunde, 3 für Fische.')key = keys(1)…elif key == '2': say('Wuff! Hunde hören Töne, die für dich zu hoch sind.')elif key == '3': say('Blubb! Fische haben keine Augenlider.')else:
const { keys, say } = require('telefon');say('Katzen, Hunde oder Fische? Drück 1 für Katzen, 2 für Hunde, 3 für Fische.');const key = keys(1);…} else if (key === '2') { say('Wuff! Hunde hören Töne, die für dich zu hoch sind.');} else if (key === '3') { say('Blubb! Fische haben keine Augenlider.');} else {
telefon/frage.rb bietet Fische als dritte Wahl an: Die Frage nennt sie, und mit der 3 sagt das Spiel »Blubb! …«. Die anderen Antworten bleiben, wie sie sind.
telefon/frage.py bietet Fische als dritte Wahl an: Die Frage nennt sie, und mit der 3 sagt das Spiel »Blubb! …«. Die anderen Antworten bleiben, wie sie sind.
telefon/frage.js bietet Fische als dritte Wahl an: Die Frage nennt sie, und mit der 3 sagt das Spiel »Blubb! …«. Die anderen Antworten bleiben, wie sie sind.
Zehn Sekunden sind lang, wenn man schon weiß, was man drücken will, und kurz
für eine schwere Frage. Wie lange keys wartet, sagst du in Sekunden:
keys(1, timeout: 5) wartet nur fünf Sekunden.
keys(1, timeout=5) wartet nur fünf Sekunden.
keys(1, 5) wartet nur fünf Sekunden.
Und mit keys(3) wartet dein Programm auf bis zu drei Tasten, etwa für eine
Geheimzahl; die Raute # beendet die Eingabe früher. Die Wartezeit
gilt für jede Taste neu: Nach jeder Taste hat man wieder die ganze Zeit für
die nächste.
Drückst du am Telefon im Workspace eine Taste, hörst du einen kurzen Ton. Genau genommen sind es zwei Töne zugleich: einer für die Zeile der Taste und einer für ihre Spalte. Die Taste 5 klingt mit 770 Hz und 1.336 Hz. Daran erkannte früher die Vermittlungsstelle, welche Taste gedrückt wurde: Sie suchte in dem, was durch die Leitung kam, nach diesen sieben Frequenzen. Das Verfahren heißt Mehrfrequenzwahl, auf Englisch DTMF (Dual-Tone Multi-Frequency).
Zwei Töne statt einem, damit eine Stimme oder ein Lied nicht aus Versehen eine Taste drückt: Dass genau zwei dieser Frequenzen zugleich und allein klingen, kommt in Sprache und Musik selten vor. Bei Telefonie über das Internet geht eine Taste heute meist als eigenes kleines Paket mit, das nur sagt, welche Taste es war; die Töne hörst du im Hörer trotzdem.
Ein Abenteuer besteht aus Szenen: Jede sagt, wo man gerade ist, und welche Taste wohin führt. Auf einer Karte sind die Szenen Kästen und die Tasten Pfeile. Diese Höhle hat erst einmal drei Szenen: davor, nach Hause und den Schatz.
Vor der Höhle wartet eine Frage wie die nach Katzen und Hunden. Lege
hoehle an:
hoehle.rb:
require 'telefon' music 'https://www.youtube.com/watch?v=-xRD8VmjBQM' sleep 3 say 'Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.' key = keys(1) if key == '1' say 'Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!' elsif key == '2' say 'Du gehst nach Hause. Vielleicht ein anderes Mal.' end say 'Ende.'
hoehle.py:
from telefon import keys, music, say, sleep music('https://www.youtube.com/watch?v=-xRD8VmjBQM') sleep(3) say('Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.') key = keys(1) if key == '1': say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!') elif key == '2': say('Du gehst nach Hause. Vielleicht ein anderes Mal.') say('Ende.')
hoehle.js:
const { keys, music, say, sleep } = require('telefon'); music('https://www.youtube.com/watch?v=-xRD8VmjBQM'); sleep(3); say('Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.'); const key = keys(1); if (key === '1') { say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!'); } else if (key === '2') { say('Du gehst nach Hause. Vielleicht ein anderes Mal.'); } say('Ende.');
Erst Musik, eine Pause, dann die Frage vor der Höhle; nach der Antwort sagt das Spiel »Ende.«, und der Anruf ist vorbei. Ruf an und probier die 1 und die 2.
Bald hat die Höhle mehr Szenen, und zu manchen kommt man mehr als einmal.
Darum bekommt jede Szene einen Namen: Sie wird eine Funktion. Pack den Satz
vom Schatz in die Funktion treasure und die Szene vor der Höhle in die
Funktion cave:
require 'telefon' def treasure say 'Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!' end def cave say 'Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.' key = keys(1) if key == '1' treasure elsif key == '2' say 'Du gehst nach Hause. Vielleicht ein anderes Mal.' end end music 'https://www.youtube.com/watch?v=-xRD8VmjBQM' sleep 3 cave say 'Ende.'
from telefon import keys, music, say, sleep def treasure(): say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!') def cave(): say('Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.') key = keys(1) if key == '1': treasure() elif key == '2': say('Du gehst nach Hause. Vielleicht ein anderes Mal.') music('https://www.youtube.com/watch?v=-xRD8VmjBQM') sleep(3) cave() say('Ende.')
const { keys, music, say, sleep } = require('telefon'); function treasure() { say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!'); } function cave() { say('Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.'); const key = keys(1); if (key === '1') { treasure(); } else if (key === '2') { say('Du gehst nach Hause. Vielleicht ein anderes Mal.'); } } music('https://www.youtube.com/watch?v=-xRD8VmjBQM'); sleep(3); cave(); say('Ende.');
Ruf an: Das Spiel klingt genau wie vorher. Die Zeilen sind dieselben, sie stehen nur an einem anderen Ort.
Von def cave bis zu seinem end steht, was zu cave gehört. Dabei
sagt das Spiel noch nichts: Erst die Zeile cave weiter unten ruft die
Funktion auf, und dann laufen ihre Zeilen, eine nach der anderen. Genauso
ruft cave die Funktion treasure auf, wenn jemand die 1 drückt.
Was unter def cave(): eingerückt steht, gehört zu cave. Dabei sagt das
Spiel noch nichts: Erst die Zeile cave() weiter unten ruft die Funktion
auf, und dann laufen ihre Zeilen, eine nach der anderen. Genauso ruft
cave die Funktion treasure auf, wenn jemand die 1 drückt.
Was in den geschweiften Klammern von function cave() steht, gehört zu
cave. Dabei sagt das Spiel noch nichts: Erst die Zeile cave(); weiter
unten ruft die Funktion auf, und dann laufen ihre Zeilen, eine nach der
anderen. Genauso ruft cave die Funktion treasure auf, wenn jemand die
1 drückt.
Die Szene »nach Hause« ist so kurz, dass sie keine eigene Funktion braucht: Sie ist nur ein Satz.
# vor die Zeile
cave unten, damit sie nicht mehr läuft, und ruf an. Achte
darauf, was du nach der Musik noch hörst. Nimm das # danach
wieder weg.
# vor die Zeile
cave() unten, damit sie nicht mehr läuft, und ruf an. Achte
darauf, was du nach der Musik noch hörst. Nimm das # danach
wieder weg.
// vor die Zeile
cave(); unten, damit sie nicht mehr läuft, und ruf an. Achte
darauf, was du nach der Musik noch hörst. Nimm die // danach
wieder weg.
Die Verzweigung in cave bekommt einen letzten Zweig, für alles außer der
1 und der 2:
elsif key == '2' say 'Du gehst nach Hause. Vielleicht ein anderes Mal.' else cave endend
elif key == '2': say('Du gehst nach Hause. Vielleicht ein anderes Mal.') else: cave()
} else if (key === '2') { say('Du gehst nach Hause. Vielleicht ein anderes Mal.'); } else { cave(); }}
Was passiert jetzt, wenn vor der Höhle niemand etwas drückt? Überleg es dir, bevor du anrufst.
Du rufst hoehle an und drückst vor der Höhle zehn Sekunden lang gar nichts. Was passiert dann?
Hier geht es weiter, sobald du deine Antwort oben abgegeben hast.
Nach zehn Sekunden sagt das Spiel den Satz vor der Höhle noch einmal. keys
gibt dann '' zurück, und im Zweig für alles andere ruft cave sich selbst
auf: Die Szene beginnt von vorn. Das passt zum Telefon. Wer nicht weiß, was
er drücken soll, hört die Wahl noch einmal. Dasselbe passiert bei einer
Taste, die in dieser Szene nichts bedeutet, etwa der 7. Auf der Karte ist
das ein Bogen zurück in denselben Kasten:
Hinter dem Eingang soll sich der Weg teilen. Die 1 vor der Höhle führt dann nicht mehr direkt zum Schatz, sondern in einen Gang: Links flackert Licht, dort liegt der Schatz. Rechts rauscht Wasser, das ist eiskalt, und man muss zurück in den Gang.
tunnel
als Funktion zwischen treasure und cave. Sie sagt
»Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser.
Drück 1 für links, 2 für rechts.« Mit der 1 geht es zum Schatz. Mit der 2
sagt sie »Das Wasser ist eiskalt. Du gehst zurück.« und beginnt von vorn,
ohne Taste ebenso. In cave führt die 1 jetzt in den Gang.
Spiel es erst auf der Karte durch: vor der Höhle die 1, im Gang die 2, dann
die 1. Welche Sätze hörst du nacheinander? Die Funktion tunnel sieht aus wie
cave, nur mit anderen Sätzen und anderen Zielen.
In Worten: Sag den Satz des Gangs. Warte auf eine Taste. Ist es die 1, geh
zum Schatz. Ist es die 2, sag den Satz vom Wasser und geh in den Gang. Sonst
geh in den Gang. »Geh in den Gang« heißt: ruf tunnel auf.
def tunnel say '…' key = keys(1) if key == '1' … elsif key == '2' say '…' … else … end end
def tunnel(): say('…') key = keys(1) if key == '1': … elif key == '2': say('…') … else: …
function tunnel() { say('…'); const key = keys(1); if (key === '1') { … } else if (key === '2') { say('…'); … } else { … } }
def tunnel say 'Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts.' key = keys(1) if key == '1' treasure elsif key == '2' say 'Das Wasser ist eiskalt. Du gehst zurück.' tunnel else tunnel end end
In cave führt die 1 in den Gang:
key = keys(1) if key == '1' tunnel elsif key == '2'
def tunnel(): say('Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts.') key = keys(1) if key == '1': treasure() elif key == '2': say('Das Wasser ist eiskalt. Du gehst zurück.') tunnel() else: tunnel()
In cave führt die 1 in den Gang:
key = keys(1) if key == '1': tunnel() elif key == '2':
function tunnel() { say('Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts.'); const key = keys(1); if (key === '1') { treasure(); } else if (key === '2') { say('Das Wasser ist eiskalt. Du gehst zurück.'); tunnel(); } else { tunnel(); } }
In cave führt die 1 in den Gang:
const key = keys(1); if (key === '1') { tunnel(); } else if (key === '2') {
In telefon/hoehle.rb führt die 1 vor der Höhle in den Gang. Dort führt die 1 zum Schatz, die 2 zum eiskalten Wasser und zurück in den Gang, und ohne Taste beginnt der Gang von vorn.
In telefon/hoehle.py führt die 1 vor der Höhle in den Gang. Dort führt die 1 zum Schatz, die 2 zum eiskalten Wasser und zurück in den Gang, und ohne Taste beginnt der Gang von vorn.
In telefon/hoehle.js führt die 1 vor der Höhle in den Gang. Dort führt die 1 zum Schatz, die 2 zum eiskalten Wasser und zurück in den Gang, und ohne Taste beginnt der Gang von vorn.
Thorsten muss nicht jeden Satz gleich sagen. Bekommt say eine Stimmung,
flüstert er, wundert sich oder klingt müde. Wer vor der Höhle die 2 drückt,
geht jetzt müde nach Hause:
elsif key == '2' say 'Du gehst nach Hause. Vielleicht ein anderes Mal.', mood: 'sleepy' else
elif key == '2': say('Du gehst nach Hause. Vielleicht ein anderes Mal.', mood='sleepy') else:
} else if (key === '2') { say('Du gehst nach Hause. Vielleicht ein anderes Mal.', { mood: 'sleepy' }); } else {
Die Stimmung steht hinter dem Text, durch ein Komma getrennt. Auf der Seite des Telefons steht sie klein über dem Satz.
Thorsten kann einen Satz in acht Stimmungen sagen; hör sie dir an, jede mit einem Satz, der zu ihr passt:
Die Sätze mit Stimmung spricht eine zweite Stimme von Thorsten, die etwas weniger klar klingt als die gewohnte. Setz Stimmungen darum sparsam ein, dort, wo sie etwas erzählen: Ein einziges Flüstern im dunklen Gang wirkt stärker als zehn.
drunk statt sleepy
ein und vergleiche beide.
Es sind zwei Sätze: Der eine steht in tunnel, der andere in treasure.
An beide kommt hinter den Text ein Komma und die Stimmung:
mood: 'whisper' für das Flüstern, mood: 'surprised' für die Überraschung.
An beide kommt hinter den Text ein Komma und die Stimmung:
mood='whisper' für das Flüstern, mood='surprised' für die Überraschung.
An beide kommt hinter den Text ein Komma und die Stimmung in geschweiften
Klammern: { mood: 'whisper' } für das Flüstern, { mood: 'surprised' } für
die Überraschung.
def treasure say 'Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!', mood: 'surprised'enddef tunnel say 'Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts.', mood: 'whisper'
def treasure(): say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!', mood='surprised')def tunnel(): say('Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts.', mood='whisper')
function treasure() { say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!', { mood: 'surprised' });}function tunnel() { say('Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts.', { mood: 'whisper' });
In telefon/hoehle.rb flüstert das Spiel den Satz im Gang, und beim Gold klingt es überrascht.
In telefon/hoehle.py flüstert das Spiel den Satz im Gang, und beim Gold klingt es überrascht.
In telefon/hoehle.js flüstert das Spiel den Satz im Gang, und beim Gold klingt es überrascht.
Musik erzählt mit, und am deutlichsten, wenn sie sich ändert. Hört sie
plötzlich auf, horcht man auf: Im dunklen Gang soll nur noch das Flüstern zu
hören sein. music nil schaltet die Musik aus.
Musik erzählt mit, und am deutlichsten, wenn sie sich ändert. Hört sie
plötzlich auf, horcht man auf: Im dunklen Gang soll nur noch das Flüstern zu
hören sein. music(None) schaltet die Musik aus.
Musik erzählt mit, und am deutlichsten, wenn sie sich ändert. Hört sie
plötzlich auf, horcht man auf: Im dunklen Gang soll nur noch das Flüstern zu
hören sein. music(null) schaltet die Musik aus.
Ein neues music mitten im Spiel ersetzt die Musik, die gerade läuft. Wer den
Schatz findet, hat Musik verdient, die nach Gewinnen klingt: »No Quarter« aus
dem Spiel Thimbleweed Park, Synthie-Pop im Stil der Achtziger. Für den Schatz
reicht die Stelle von 0:16 bis 0:32, und die wiederholt sich, solange sie
läuft. Sechzehn Sekunden sind bei diesem Stück genau acht Takte, darum springt
die Wiederholung nicht mitten aus dem Takt.
tunnel hört die Musik auf. Am Anfang von treasure
spielt »No Quarter« (https://www.youtube.com/watch?v=oR450XGc-j4) von 0:16 bis 0:32.
Damit man die Musik nach dem Satz noch hört, wartet treasure
danach acht Sekunden.
Für jede der beiden Stellen reicht eine Zeile. Wie music nur einen
Ausschnitt spielt, steht oben unter »Musik im Hintergrund«: mit start und
stop.
def treasure music '…', start: '…', stop: '…' say '…', mood: 'surprised' sleep … end def tunnel music … say '…', mood: 'whisper'
def treasure(): music('…', start='…', stop='…') say('…', mood='surprised') sleep(…) def tunnel(): music(…) say('…', mood='whisper')
function treasure() { music('…', { start: '…', stop: '…' }); say('…', { mood: 'surprised' }); sleep(…); } function tunnel() { music(…); say('…', { mood: 'whisper' });
def treasure music 'https://www.youtube.com/watch?v=oR450XGc-j4', start: '0:16', stop: '0:32' say 'Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!', mood: 'surprised' sleep 8enddef tunnel music nil
def treasure(): music('https://www.youtube.com/watch?v=oR450XGc-j4', start='0:16', stop='0:32') say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!', mood='surprised') sleep(8)def tunnel(): music(None)
function treasure() { music('https://www.youtube.com/watch?v=oR450XGc-j4', { start: '0:16', stop: '0:32' }); say('Im Licht einer Fackel glänzt eine Kiste voller Gold. Du hast den Schatz gefunden!', { mood: 'surprised' }); sleep(8);}function tunnel() { music(null);
In telefon/hoehle.rb hört die Musik im Gang auf, und beim Schatz spielt »No Quarter« von 0:16 bis 0:32.
In telefon/hoehle.py hört die Musik im Gang auf, und beim Schatz spielt »No Quarter« von 0:16 bis 0:32.
In telefon/hoehle.js hört die Musik im Gang auf, und beim Schatz spielt »No Quarter« von 0:16 bis 0:32.
Wer zum dritten Mal anruft, kennt den Satz vor der Höhle auswendig. Eine
Taste, die man währenddessen drückt, geht zwar nicht verloren, aber den Satz
muss man trotzdem bis zum Ende anhören. Mit interrupt bricht er ab, sobald
jemand eine Taste drückt, und das nächste keys bekommt genau diese Taste:
def cave say 'Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.', interrupt: true
def cave(): say('Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.', interrupt=True)
function cave() { say('Du stehst vor einer dunklen Höhle. Drück 1, um hineinzugehen, oder 2, um nach Hause zu gehen.', { interrupt: true });
Das passt zu Sätzen, die man nach dem ersten Mal kennt, wie der Wahl vor der
Höhle. Ein Satz mit einem Hinweis, den niemand verpassen darf, bleibt besser
ohne interrupt.
Bisher endet ein Anruf, wenn das Programm zu Ende ist. Manchmal soll er
mittendrin enden: Wer im Gang ins Wasser springt, kommt nicht wieder. hangup
legt sofort auf, egal in welcher Szene das Spiel gerade ist. Danach kommt kein
Satz mehr, auch nicht das »Ende.« am Schluss des Programms, und auf dem
Telefon ertönt das Besetztzeichen.
Bisher endet ein Anruf, wenn das Programm zu Ende ist. Manchmal soll er
mittendrin enden: Wer im Gang ins Wasser springt, kommt nicht wieder.
hangup() legt sofort auf, egal in welcher Szene das Spiel gerade ist. Danach
kommt kein Satz mehr, auch nicht das »Ende.« am Schluss des Programms, und auf
dem Telefon ertönt das Besetztzeichen.
Bisher endet ein Anruf, wenn das Programm zu Ende ist. Manchmal soll er
mittendrin enden: Wer im Gang ins Wasser springt, kommt nicht wieder.
hangup() legt sofort auf, egal in welcher Szene das Spiel gerade ist. Danach
kommt kein Satz mehr, auch nicht das »Ende.« am Schluss des Programms, und auf
dem Telefon ertönt das Besetztzeichen.
Die 3 bekommt einen eigenen Zweig vor dem else, wie die Fische in der
Frage nach den Tieren.
Reicht nicht auch der Satz allein? Spiel es im Kopf durch: Nach dem Satz ist
tunnel zu Ende, das Programm macht in cave weiter, dann ist auch cave zu
Ende, und ganz unten sagt das Programm noch »Ende.« Erst das Auflegen beendet
den Anruf sofort.
elsif key == '3' say '…' …
elif key == '3': say('…') …
In der ersten Zeile holt from telefon import dann auch hangup.
} else if (key === '3') { say('…'); …
In der ersten Zeile holt require('telefon') dann auch hangup.
def tunnel music nil say 'Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts, 3, um ins Wasser zu springen.', mood: 'whisper' … elsif key == '2' say 'Das Wasser ist eiskalt. Du gehst zurück.' tunnel elsif key == '3' say 'Du springst ins Wasser. Die Strömung reißt dich fort, hinaus in die Nacht.' hangup else
from telefon import hangup, keys, music, say, sleep…def tunnel(): music(None) say('Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts, 3, um ins Wasser zu springen.', mood='whisper') … elif key == '2': say('Das Wasser ist eiskalt. Du gehst zurück.') tunnel() elif key == '3': say('Du springst ins Wasser. Die Strömung reißt dich fort, hinaus in die Nacht.') hangup() else:
const { hangup, keys, music, say, sleep } = require('telefon');…function tunnel() { music(null); say('Drinnen teilt sich der Gang. Links flackert Licht, rechts rauscht Wasser. Drück 1 für links, 2 für rechts, 3, um ins Wasser zu springen.', { mood: 'whisper' }); … } else if (key === '2') { say('Das Wasser ist eiskalt. Du gehst zurück.'); tunnel(); } else if (key === '3') { say('Du springst ins Wasser. Die Strömung reißt dich fort, hinaus in die Nacht.'); hangup(); } else {
In telefon/hoehle.rb nennt der Gang eine dritte Wahl. Mit der 3 springt man ins Wasser, das Spiel sagt »… Strömung …« und legt auf, ohne danach noch »Ende.« zu sagen.
In telefon/hoehle.py nennt der Gang eine dritte Wahl. Mit der 3 springt man ins Wasser, das Spiel sagt »… Strömung …« und legt auf, ohne danach noch »Ende.« zu sagen.
In telefon/hoehle.js nennt der Gang eine dritte Wahl. Mit der 3 springt man ins Wasser, das Spiel sagt »… Strömung …« und legt auf, ohne danach noch »Ende.« zu sagen.
Thorsten liest alles, was in say steht, wie einen deutschen Text. Meistens
klingt das richtig. Bei Zahlen, Abkürzungen und englischen Wörtern lohnt es
sich, genau hinzuhören:
| Im Text | Thorsten sagt | So klingt es anders |
|---|---|---|
Raum 123 |
»Raum hundertdreiundzwanzig« |
Raum 1 2 3: »Raum eins zwei drei« |
ZDF |
»Zett De Eff«: Abkürzungen buchstabiert er | |
Psst, Hm, Brr
|
den Laut, nicht die Buchstaben | |
Game Over |
»Gahme Ohver«, deutsch gelesen | [[ ɡˈeɪm ]] over |
Ein Komma macht eine kurze Pause, ein Punkt, ein Fragezeichen oder ein
Ausrufezeichen eine längere. Zwischen zwei doppelten eckigen Klammern steht
Lautschrift, das Internationale Phonetische Alphabet (IPA): Dann spricht
Thorsten genau diese Laute. Das Zeichen ˈ steht vor der betonten Silbe, ː
macht den Laut davor lang. Meist reicht es, nur das Wort in Lautschrift zu
schreiben, das falsch klingt: »over« spricht Thorsten so, wie man es auf
Deutsch meistens sagt.
Leider verloren. [[ ɡˈeɪm ]] over!
Die Lautschrift eines Wortes steht im Wiktionary unter »Aussprache«, bei englischen Wörtern im englischen Wiktionary. Die Zeichen kopierst du von dort. Auf der Seite des Telefons steht die Lautschrift ohne die Klammern.
Jetzt erfindest du dein eigenes Abenteuer: eine Burg, ein Raumschiff, ein Wald, ein Schulgebäude nach Mitternacht. Zeichne zuerst die Karte auf Papier, mit einem Kasten für jede Szene und einem Pfeil für jede Taste, wie bei der Höhle. Dabei merkst du, ob jede Szene einen Ausgang hat und ob man das Ende überhaupt erreichen kann.
Deine Geschichte hat mindestens vier Szenen und zwei verschiedene Enden, ein gutes und ein schlechtes zum Beispiel. Jede Szene sagt, welche Taste wohin führt; wer anruft, sieht deine Karte ja nicht.
Schreib dein Spiel in eine neue Datei geschichte.rb im Ordner telefon:
eine Funktion für jede Szene, unten die Musik und der Aufruf der ersten
Szene. Ruf nach jeder neuen Szene einmal an und spiel sie durch.
Schreib dein Spiel in eine neue Datei geschichte.py im Ordner telefon:
eine Funktion für jede Szene, unten die Musik und der Aufruf der ersten
Szene. Ruf nach jeder neuen Szene einmal an und spiel sie durch.
Schreib dein Spiel in eine neue Datei geschichte.js im Ordner telefon:
eine Funktion für jede Szene, unten die Musik und der Aufruf der ersten
Szene. Ruf nach jeder neuen Szene einmal an und spiel sie durch.
Was ein Spiel am Telefon gut macht:
start und stop reicht oft. Und Stille ist
auch Musik.interrupt für Sätze, die man beim zweiten Mal schon
kennt.hangup auf, und das Besetztzeichen sagt den Rest.telefon/geschichte.rb spielt Musik, sagt etwas und wartet dann auf eine Taste.
telefon/geschichte.py spielt Musik, sagt etwas und wartet dann auf eine Taste.
telefon/geschichte.js spielt Musik, sagt etwas und wartet dann auf eine Taste.
Lass jemanden aus deiner Klasse an deinem Rechner anrufen, ohne dass er oder sie deinen Code oder deine Karte sieht. Schau zu, ohne zu helfen: Wo zögert die Person, wo drückt sie etwas, das du nicht erwartet hast, wo kommt sie nicht weiter? Danach änderst du dein Spiel.
Wer hat dein Spiel gespielt? Wo hat die Person gezögert oder etwas anderes gedrückt, als du erwartet hast, und was hast du danach geändert?
Ist dein Spiel fertig, kommt es ins Telefonbuch: Dort steht es mit seinem Titel und einer Nummer, unter der man es anruft. Such dir die Nummer aus, mit drei oder vier Ziffern, oder ein Wort aus drei oder vier Buchstaben wie DINO: Man wählt es mit den Tasten, auf denen die Buchstaben stehen, hier 3466. Bevor es im Telefonbuch steht, sieht es sich jemand an, und du bekommst eine E-Mail, ob es veröffentlicht ist. Im Telefonbuch steht nicht, wer es geschrieben hat, nur der Titel, der Satz dazu und die Nummer.
Vorher gibt dein Spiel sich selbst einen Namen und einen Satz, der im Telefonbuch unter dem Namen steht. Beides gehört an den Anfang deiner Datei:
require 'telefon'title 'Die Höhle der Echos'subtitle 'Ein Abenteuer mit drei Wegen und einem Schatz.'
from telefon import keys, music, say, sleep, subtitle, title title('Die Höhle der Echos') subtitle('Ein Abenteuer mit drei Wegen und einem Schatz.')
const { keys, music, say, sleep, subtitle, title } = require('telefon'); title('Die Höhle der Echos'); subtitle('Ein Abenteuer mit drei Wegen und einem Schatz.');
Das Telefon zeigt den Namen an, sobald dein Spiel ihn sagt.
Eingereicht wird eine Kopie deines Spiels und der Dateien daneben, etwa deiner MP3s: Änderst du danach etwas, reich es noch einmal ein, unter derselben Nummer; die neue Fassung ersetzt die alte, sobald sie freigegeben ist. Zurückziehen kannst du dein Spiel jederzeit, dann ist seine Nummer wieder frei.
Deine Spiele werden geladen …
Ein Extra für Schnelle. Wer es auslässt, springt zu Wie geht es weiter?.
Am Ende der Höhle könnte eine Tür mit einem Zahlenschloss warten. keys(3)
wartet auf bis zu drei Tasten, und wer weniger braucht, drückt danach die
Raute:
def door say 'Eine Tür mit einem Zahlenschloss. Gib drei Ziffern ein.' code = keys(3) if code == '472' say 'Klick. Die Tür springt auf.' else say 'Nichts passiert.' door end end
def door(): say('Eine Tür mit einem Zahlenschloss. Gib drei Ziffern ein.') code = keys(3) if code == '472': say('Klick. Die Tür springt auf.') else: say('Nichts passiert.') door()
function door() { say('Eine Tür mit einem Zahlenschloss. Gib drei Ziffern ein.'); const code = keys(3); if (code === '472') { say('Klick. Die Tür springt auf.'); } else { say('Nichts passiert.'); door(); } }
Woher kennt man die Zahl? Vielleicht sagt sie eine andere Szene nebenbei: »Auf einem Zettel an der Wand steht 472.« Wer gut zuhört, kommt weiter.
keys(3) nach zehn Sekunden zurück? Und was, wenn du nach zwei
Ziffern die Raute drückst?
Dein Abenteuer merkt sich noch nichts: Wer die Fackel nimmt, hat sie in der nächsten Szene schon wieder vergessen. Wie eine Welt Gegenstände, Räume und eine Tasche bekommt, die sich alles merkt, baust du im Textadventure aus Objekten. Und wenn du lieber schreibst als programmierst: Mit BIF erzählst du eine Geschichte mit Entscheidungen, Seite für Seite.
Sind es viele Szenen, wird jede neue Funktion fast eine Kopie der vorigen. Dann lohnt es sich, die Szenen als Daten aufzuschreiben: ein Hash (Dictionary) mit dem Namen jeder Szene, ihrem Text und wohin ihre Tasten führen, und eine einzige Schleife, die von Szene zu Szene geht. Wie ein Hash funktioniert, übst du in den Katas zu Dictionaries.
