Kategorien
Allgemein

Dialog, deutsche Sprachbibliothek

Die deutsche Sprachbibliothek für Linus Åkessons Dialog Sprache macht große Schritte Richtung Betatestphase.

Eine der wichtigsten Änderungen seit Veröffentlichung ist die Möglichkeit, Umlaute in der Eingabe mit den im Kreuzworträtsel üblichen Ersetzungen auszutauschen, also beispielsweise „ae“ statt „ä“.

Das mag als eine Kleinigkeit erscheinen, ist aber wichtig, sobald Jemand mit einer fremdsprachigen Tatstatur ein deutsches Spiel spielen möchte.

Möglich macht dies eine Erweiterung der Funktionen der virtuellen Maschine, die Wörter in Arrays teilen und später wieder zusammenfügen kann. Also wird aus [grün] zunächst [g r ü n], dann [g r u e n] und später wieder [gruen].

Diese Änderung betrifft das gesamte Vokabular eines Spiels. Um parserkonform zu bleiben, muss der Autor von jetzt an (ab Commit „6e2ed8d“) bei allen (dict *) Prädikaten nun Umlaute wie „ä“ mit „ae“ und „ß“ mit „ss“ ersetzen. Dank moderner Texttools ist das glücklicherweise kein größeres Problem.

Somit sind nun alle Features, die ich für eine komfortable Erstellung eines Textadventures in deutscher Sprache mit Dialog als sinnvoll erachte, implementiert.

Die Bibliothek mag noch kleinere Verbesserungen erfahren, da ich momentan ein neues Textadventure schreibe. Noch will ich nichts Näheres dazu sagen, es gibt aber schon die Vorversion einer Covers und die Hoffnung, dass es bald in die Betatestphase geht.

Stay tuned and stay at home.

Kategorien
Review

Zozzled

by Steph Cherrywell

„Zozzled“ ist einer der wenigen Titel, die ich aus der Vielzahl der eingereichten Spiele der IF-Comp 2019 gespielt habe.

Steph Cherrywell, bekannt für ihre Web-Comics, hat mit Zozzled bereits ihr sechstes Textadventure veröffentlicht. Unter ihren Werken befinden sich beispielsweise Brain Guzzlers from Beyond!, Jacqueline, Jungle Queen! oder Whitefield Academy of Witchcraft.

Eines vorweg: ich bin ein großer Fan von „Jaqueline, Jungle Queen“ und von Stephs Schreibstil im Allgemeinen.

Stephs Werke sind gekennzeichnet von ihrem ganz eigenen Humor und Stil, der auch im Text Stephs Affinität zum Comicgenre durchscheinen lässt.

Für manche mag das überzogen oder kitschig wirken, mich hingegen erinnert Stephs Stil in sehr positiver Weise an alte Infocom-Texte. Abgedrehter Humor und Phantasie scheinen an allen Ecken und Enden des Spiels durch.

Das „geistreiche“ Zozzled hat mich auf mehreren Ebenen überzeugt.

Die Rätsel sind konsistent und einfallsreich. Das Setting ist hervorragend ausgedacht und umgesetzt. Das Poseidon Hotel lässt das 20er Jahre Flair aufleben, eine Zeit, die geprägt ist von den Wunderwerken der Technik und der Faszination der Meere.

Dies alles wird durch die detailverliebte Umsetzung der Umgebung meisterhaft zum Leben erweckt.

Wunderbar fügen sich auch die NPCs in das Setting ein, mein Favorit ist die Meerjungfrau in dem großen Wassertank in der Hotellobby.

Ein kleiner Kritikpunkt wäre für mich das wenig interaktive Ende, das einfach zu viel Text am Stück produziert und damit den Spieler fast erschlägt.

Hier ist wohl die Zeit etwas knapp geworden, so dass die Autorin das, was noch gesagt werden muss, der Einfachheit halber in lange Textpassagen gepackt hat. Das tut aber der Atmosphäre keinen Abbruch und zeigt andererseits nur, wie gut ausgedacht diese Geschichte und die Akteure sind.

Fazit: Wer gerne in die 20er Jahre eintauchen möchte und sich an herrlich abgedrehtem Infocom-Humor erfreut, liegt hier goldrichtig. Daumen hoch, „posi-tutely!“

Kategorien
Allgemein

Interview mit Marc Blanc und Dave Lebling

„The Wired“ hat ein Interview mit Marc Blanc und Dave Lebling geführt, aus deren Feder beispielsweise die „Zork“ und die „Enchanter“ Reihe entsprungen sind.

Das Besondere ist: es handelt sich um ein Interview in Textadventure-Form. Der Inhalt ist, trotz des fortgeschrittenen Alters von acht Jahren, immer noch online verfügbar.

Anlass des Interviews war der Pioneer Award, der von der „Academy of Interactive Arts and Sciences“ an Pioniere der Computerspiel-Industrie verliehen wurde. Marc Blanc und Dave Lebling wurden als Mitbegründer des Infocom Labels honoriert.

Hier kommt ihr zum Interview.

Kategorien
Allgemein

Advent Door

by Andrew Plotkin

„Advent Door“ geht auf eine Idee Andrew Plotkins zurück, 24 kleine IF Werke in einen Adventskalender zu packen. Ein weiterer Versuch, ein kollaboratives IF Projekt auf den Weg zu bringen, der aber leider scheiterte.

Trotzdem wurde mit „Advent Door“ Plotkins Beitrag veröffentlicht. Es handelt sich um eine sehr kurze Geschichte, die sich um einen cleveren Rätselmechanismus dreht.

Schade, dass aus dem Projekt nichts geworden ist, zeigt doch das kleine Beispiel gelungen, in welche Richtung so etwas gehen kann.

Wer spielen möchte, findet Plotkins Blogbeitrag hier.

Kategorien
Dialog

Ballpark – Inform Example No. 60

Das Inform-Beispiel Nr. 60, nach Dialog portiert

%% Manchmal ist es besser, eine Zahl eher vage als exakt zu
%% bezeichnen, beispielsweise dem Spieler zu erzählen, dass 
%% sich viele Menschen in dem Saal befinden, als exakt 42.

%% Die Idee ist, sich durch eine Liste zu arbeiten, die hier 
%% als globale Variable definiert wird, und den Text in der 
%% Liste auszugeben, sobald die Zahl höher ist als der 
%% Eintrag.

(current player #player)
(#player is #in #stadium)

(global variable (round_numbers [[1 keine] [2 einen] [3 ein paar] [6 einige wenige] [11 einige] [21 viele] [1000 sehr sehr viele]]))

(population of $ is $)
	(fail)

#stadium
(room *)
(name *)	Stadion
(from * go #west to #hotdogstand)
(from * go #south to #restroom)
(population of * is 500)

#hotdogstand
(room *)
(name *)	Hot Dog Stand
(population of * is )
(from * go #east to #stadium)
(population of * is 3)

#restroom
(room *)
(name *)	Stadion
(population of * is )
(from * go #north to #stadium)
(population of * is 750)

(look (room $Room))
	(population of $Room is $Number)
	Hier siehst du
	(round_numbers $List)
	(get best entry of $Number in $List)

(get best entry of $N in [$Check | $Rest])
	([$F | $Else] = $Check)
	(if) ($N < $F) (then)
		(display $Else) 
	(endif)
	(get best entry of $N in $Rest)

(display [$First | $Rest])
	$First
	(display $Rest)

(display [])
	Menschen.
	(stop)

%% Testen mit w / o / s
Kategorien
Dialog

Bad Hair Day – Inform Example No. 84

Das Inform Beispiel Nr. 84, nach Dialog portiert

(current player #player)
(#player is #in #room)

#room
(room *)
(name *)	Raum
(look *)
		Ein Spiegel hängt über dem Tisch, eine verlockende Möglichkeit, dich zu betrachten, bevor du zu den anderen hineingehst.

(instead of [examine #player])
	Ok, du siehst prima aus.

%% Testen mit betrachte dich
Kategorien
Dialog

America Stands Tall

Das Inform Beispiel, portiert nach Dialog

%% Im ovalen Büro soll die Größe geschätzt werden. Dazu ist ein wenig
%% Anpassung im Bereich der Grammatikschablonen notwenig und auch das
%% Abfangen unvollständiger Eingabe wie "schätze (person)"

(current player #player)
(#player is #in #room)
(height of #player is 1 m 75 cm)

(height of $ is $ m $ cm)
	(fail)

#room
(room *)
(name *)	Ovales Büro
(* is neutrum)

#josh
(male actor *)
(name *)	Josh(-s)
(dict *)	josh
(* is #in #room)
(proper *)
(appearance * $ $)	Josh und Toby sind hier.
(height of * is 1 m 85 cm)

#toby
(male actor *)
(name *)	Toby(-s)
(dict *)	toby
(* is #in #room)
(proper *)
(height of * is 1 m 70 cm)

(describe action [guess $NPC to $Meter and $Zentimeter])
	jemanden auf m und cm (zu) schätzen

(understand infinitve [schätzen] as [schätz])

(understand [schätz | $Words] as [guess $NPC to $Meter and $Zentimeter])
	*(split $Words by [auf] into $Left and $Right)
	*(understand $Left as single object $NPC)
	*(split $Right by [m meter] into $First and $Rest)
	*(understand $First as number $Meter)
	*(split $Rest by [cm zentimeter] into $Second and $Unused)
	*(understand $Second as number $Zentimeter)

(describe action [guess $NPC to $Meter])
	jemanden auf m (zu) schätzen

(unlikely [guess $NPC to $Meter])

(understand [schätz | $Words] as [guess $NPC to $Meter])
	*(split $Words by [auf] into $Left and $Rest)
	*(understand $Left as single object $NPC)
	*(split $Rest by [m meter] into $First and $Unused)
	*(understand $First as number $Meter)

(understand [schätz | $Words] as [guess $Object])
	*(understand $Words as single object $Object)

(understand [schätz] as [guess])

(describe action [guess $NPC])
	jemanden (zu) schätzen

(very unlikely [guess $NPC])

(perform [guess])
	Wen?
	(asking for object in [guess []])

(perform [guess $NPC])
	Auf wieviele m?
	(get input $Input)
	(understand $Input as number $Meter)
	Und wieviele cm?
	(get input $Input2)
	(understand $Input2 as number $Zentimeter)
	(try [guess $NPC to $Meter and $Zentimeter])

(perform [guess $NPC to $Meter])
	Und wieviele cm?
	(get input $Input)
	(understand $Input as number $Zentimeter)
	(try [guess $NPC to $Meter and $Zentimeter])

(perform [guess $NPC to $Meter and $Zentimeter])
	(height of $NPC is $isMeter m $isZentimeter cm)
	(if) ($Meter > $isMeter) (then)
		(kleiner $NPC).
		(stop)
	(elseif) ($Meter < $isMeter) (then)
		(größer $NPC).
		(stop)
	(elseif) ($Zentimeter > $isZentimeter) (then)
		(kleiner $NPC).
		(stop)
	(elseif) ($Zentimeter < $isZentimeter) (then)
		(größer $NPC).
		(stop)
	(endif)
	Du liegst goldrichtig.

(kleiner $NPC)
	Du liegst daneben, (der $NPC) (ist $NPC) kleiner

(größer $NPC)
	Du liegst daneben, (der $NPC) (ist $NPC) größer
Kategorien
Dialog

All Roads Lead to Mars – Inform Example No. 78

Das Inform-Beispiel Nr. 178, nach Dialog portiert

%% Angenommen wir möchten es dem Spieler ermöglichen, sich frei in
%% jeglicher Richtung zu bewegen, aber gleichzeitig zu kontrollieren, 
%% in welcher Reihenfolge er die Räume besucht. Das Erzählen der 
%% Geschichte steht eher im Mittelpunkt, als die genaue Abbildung
%% einer Karte.

%% Hier wird die Problematik über eine Liste gelöst, in der die 
%% Verbindungen der Räume abgelegt werden, wenn diese noch nicht 
%% besucht wurden. Getestet wird außerdem, ob die Verbindung bereits
%% zwischen zwei anderen Räumen besteht.

(global variable (connector []))

($ is connected) 
	(fail)

(nextroom from $ is $)
	(fail)

(current player #player)
(#player is #in #open_plain)

#open_plain
(room *)
(name *)	weite(e) Ebene
(room header *)	Weite Ebene
(look *)
		Eine weite Ebene, offen in jeder Richtung.
(* is feminin)
(nextroom from * is #hilly_place)

%% (from * go $ to #hilly_place)

#hilly_place
(room *)
(name *)	hügelig(er) Ort(-es)
(room header *)	Hügeliger Ort
(look *)
		Das flache Grasland wird hier zu einer hügeligen Gegend, die
		dir aber gleichfalls alle Wege offen lässt.
(* is maskulin)
(nextroom from * is #stream)

%% (from * go $ to #stream)

#stream
(room *)
(name *)	Strom(-es)
(room header *)	Am Strom
(look *)
		Das ist der dritte Ort, den du heute besuchst und der Strom ist dir sehr willkommen. Wie erfrischend!
(* is maskulin)

(before [leave $Room $Dir])
	(nextroom from $Room is $NextRoom)
	~($NextRoom is visited)
	~(from $Room go $Dir to $)
	(connector $List)
	(append $List [[$Room $Dir $NextRoom]] $New)
	(now) (connector $New)
	(opposite of $Dir is $Opp)
	(append $New [[$NextRoom $Opp $Room]] $Reverse)
	(now) (connector $Reverse)

(from $Room go $Dir to $NextRoom)
	(connector $List)
	([$Room $Dir $NextRoom] is one of $List)

%% Testen mit "n / s / o / o". 
Kategorien
Dialog

Age of Steam – Inform Example No. 156

Das Inform Beispel Nr. 156, nach Dialog portiert

(intro)
	(now) (scenetime 0)
	(now) (time 539) %%08:59 Uhr
	(banner)
	(try [look])

(current player #player)
(#player is #in #station)

(global variable (time $))
(global variable (scenetime $))
(global variable (arrival $))

#station
(room *)
(name *)	Bahnstation
(look *)
		Der Halt "Eynforme" ist eine erhöhte Plattform, gesäumt von Dotterblumen, eine Bedarfshaltestelle mit einem Signal und einem Wassertank.
(* is feminin)

(on every tick in *)
    (scenetime $A)
    ($A plus 1 into $B)
    (now) (scenetime $B)
	(if) ($B = 3) (then)
		(now) (#flying_scotsman is #in *)
		(time $time) 
		(now) (arrival $time)
		Der Flying Scotsman zieht sich stampfend die Platform hinauf, umgeben von dichten Rauchschwaden.
	(elseif) ($B = 6) (then)
		(now) (#flying_scotsman is nowhere)
		 Der Flying Scotsman setzt sich wieder in Bewegung und nimmt nach dem Kreischen der gelösten Bremsen unglaublich schnell Fahrt auf, bis er schließlich hinter dem Hügel verschwindet. Alles ist plötzlich wieder still.
	(endif)

#flying_scotsman
(item *)
(name *)	Flying Scotsman
(dict *)	flying scotsman zug
(* is handled)
(* is maskulin)
(fine where it is *)

(appearance * in $)
		Der Flying Scotsman, der schnellste Zug der Welt, ist zum
		völligen Stillstand gekommen.

(instead of [enter *])
		Leider tankt der
		(arrival $time)
		(say time $time)
		Zug nur Wasser und nimmt niemand mit.

(on every tick)
    (time $A)
    ($A plus 1 into $B)
    (now) (time $B)

(say time $A)
    ($A divided by 60 into $C)
    ($A modulo 60 into $D)
    $C:(no space)
    (if) ($D < 10) (then)
        0(no space)
    (endif)
    $D

%% Testen: "z / z / z / steig in zug / z / z"
Kategorien
Dialog

Actor’s studio – Inform Example No. 221

Das Inform-Beispiel Nr. 221, nach Dialog portiert

%% Beispiel Nr. 221 der Inform Dokumentation
%% Eine Videokamera, die Ereignisse aufzeichnet 
%% und sie dann
%% mit einem Zeitstempel wieder abspielt.

(global variable (videostream []))
(global variable (time $))
~(memory is empty)

(global variable (camera mode $))

(setting $) (fail)

#idle 
(name *) Ruhemodus 
(dict *) ruhemodus ruhe
(setting *)
(* is #partof #camera)

#recording 
(name *) Aufnahme 
(dict *) aufnahme
(setting *)
(* is #partof #camera)

#replaying 
(name *) Wiedergabe 
(dict *) wiedergabe
(setting *)
(* is #partof #camera)

(style class @score)
	width: 20ch;
	float: right;

(intro)
    (now) (time 542)
    (now) (camera mode #idle)
    (try [look])
    
(redraw status bar)
	(status bar @status) {
        (time headline)
        (location headline)
	}

(time headline)
    (div @score) {
        (time $Time)
        Zeit: 
        (say time $Time)
    }

(say time $A)
    ($A divided by 60 into $C)
    ($A modulo 60 into $D)
    $C:(no space)
    (if) ($D < 10) (then)
        0(no space)
    (endif)
    $D

(after $Action)
    (camera mode #recording)
    ~($Action = [wait])
    ~($Action = [$ #camera $ $])
    (videostream $Video)
    (length of $Video into $Len)
    (if) ($Len < 48) (then)
        (time $T)
        (append [$T | [$Action]] $Video $New)
        (now) (videostream $New)
    (else)
        (now) (camera mode #idle)
        Der Speicher der Videokamera ist voll 
        und sie schaltet in den Ruhemodus.
    (endif)

(on every tick)
    (time $A)
    ($A plus 1 into $B)
    (now) (time $B)

(on every tick)
    (camera mode #replaying)
    (if) ~(memory is empty) (then)
        (videostream $Video)
        (reverse $Video $List)
        (now) (memory is empty)
        (report actions from list $List)
    (else)
        Du siehst nur Rauschen auf der Videokamera.
    (endif)

(report actions from list [$Action $Time | $Tail])
    (line)Um (say time $Time) Uhr hat die Kamera aufgezeichnet, als du dabei warst,
    (describe infinitive action $Action).
	(report actions from list $Tail)

(current player #player)
(#player is #in #actor_studio)

#actor_studio
(room *)
(name *)    Filmstudio(-s)
(* is maskulin)

#lucas
(male actor *)
(name *)    Lucas
(proper *)
(dict *)    lucas mann typ
(* is #in #actor_studio)
(appearance #lucas $ $)
    Lucas ist hier.

(prevent [tell #lucas to take $Obj])
    {
        ($Obj is #heldby $NPC)
        (Der $NPC) (hat $NPC) (den $Obj) schon.
    (or)
        ~(item $Obj)
        (Der $NPC) (kann $NPC) (den $Obj) nicht nehmen.
    }

(perform [tell #lucas to take $Obj])
    (let #lucas take $Obj)

(perform [tell #lucas to eat $Obj])
    (let #lucas eat $Obj)

(let $NPC eat $Obj)
    (if) ~(edible $Obj) (then)
        (fail)
    (endif)
    (if) (player can see $Obj) (then)
        (if) ~($Obj is #heldby $NPC) (then)
            \(Erst nimmt Lucas (den $Obj)\)(line)
            (now) ($Obj is #heldby $NPC)
        (endif)
		(narrate $NPC eating $Obj)
	(endif)
	(now) ($Obj is nowhere)

(narrate $NPC eating $Obj)
	(Der $NPC) (isst $NPC) (den $Obj).

#croissant
(item *)
(name *)    Croissant(-s)
(dict *)    croissant
(edible *)
(* is handled)
(* is neutrum)
(* is #in #actor_studio)

#camera
(item *)
(name *)    Videokamera
(dict *)    video kamera videokamera
(descr *)
        Die Videokamera ist momentan auf 
        (camera mode $Mode)
        (name $Mode) eingestellt.
(* is feminin)
(* is #in #actor_studio)
(* is handled)

(describe action [set $Obj to $Setting])
	(den $Obj) auf (name $Setting) einstellen

(understand infinitive [einstellen/stellen] as Verb [stell])

(unlikely [put $Obj #on $Dest])
	($Obj = #camera)

(understand [stell | $Words] as [set $Obj to $Setting])
    *(split $Words by [auf] into $Left and $Right)
    *(understand $Left as single object $Obj)
    *(understand $Right as single object $Setting)

(understand [stell ein | $Words] as [set $Obj to $Setting])
    *(split $Words by [auf] into $Left and $Right)
    *(understand $Left as single object $Obj)
    *(understand $Right as single object $Setting)

(refuse [set $Obj to $Setting])
    (just)
    ~($Setting is one of [#idle #recording #replaying])
    Das ist keine gültige Einstellung für (den $Obj).

(perform [set $Obj to $Setting])
    (now) (camera mode $Setting)
    Die Videokamera ist nun auf (name $Setting) eingestellt.
    (if) ($Setting is one of [#recording #idle]) (then)
        (now) ~(memory is empty)
    (endif)

%% Testen: "stell kamera auf aufnahme / x lucas / winke / lucas, iss croissant / stell kamera auf wiedergabe / z"