Fix contact transitions and dining car access

This commit is contained in:
2026-05-24 18:14:16 +02:00
parent 510901f5bf
commit eef90f3471
8 changed files with 333 additions and 166 deletions
+170 -141
View File
@@ -19,9 +19,9 @@
// ============================================================================
=== train_intro_start ===
~ loc_move_to(loc_train_compartment)
~ character_move_to(viktor, loc_train_compartment)
~ companion_join(viktor)
~ loc_move_to(loc_train_compartment)
~ contact_sync()
Der Zug hat Wien hinter sich gelassen, doch du hast Wien noch nicht hinter dir gelassen. #chapter[Das Abteil] #music[Kaiserpunk Waltz.mp3](crossfade, loop, lead=8)
@@ -122,7 +122,7 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
#alert[Links erscheinen Entscheidungen. Du kannst sie mit der Maus wählen oder mit der angezeigten Taste auslösen. Das hervorgehobene Wort beschreibt, was Valerie versucht; Kürzel wie L für Schaue oder X für Untersuche folgen Textadventure-Gewohnheiten.]
}
* {state_reached(freshen_up_started)} {state_before(freshen_up_done)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach unerledigtem Frischmachen] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(freshen_up_started) && state_before(freshen_up_done))} [AUTO: Viktors Rückkehr nach unerledigtem Frischmachen] #auto
Viktor hebt den Blick. Du bist zu rasch zurück, um die Begründung erfüllt zu haben, mit der du gegangen bist.
„Das war ein sehr kurzer Augenblick“, sagt er.
@@ -131,7 +131,7 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_closed)
-> TURN
* {state_reached(freshen_up_done)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach Frischmachen] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(freshen_up_done))} [AUTO: Viktors Rückkehr nach Frischmachen] #auto
Viktor hebt den Blick, als du wieder eintrittst. Er bemerkt zuerst nicht dein Gesicht, sondern die Arbeit daran: glattere Nadeln, kühlere Hände, ein Blick, der wieder dort sitzt, wo andere ihn erwarten.
„Besser?“, fragt er.
@@ -140,7 +140,7 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_reliable)
-> TURN
* {state_reached(explore_train_started)} {state_before(explore_train_done)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach kurzer Erkundung] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(explore_train_started) && state_before(explore_train_done))} [AUTO: Viktors Rückkehr nach kurzer Erkundung] #auto
Viktor hebt den Blick und sieht nicht zu deinem Gesicht, sondern zu deinen Schuhen, als könne der Gang Staub genug verraten.
„Und?“, fragt er. „Reicht der Zug weiter, als er sollte?“
@@ -149,7 +149,7 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_insightful)
-> TURN
* {state_reached(explore_train_done)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach Erkundung] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(explore_train_done))} [AUTO: Viktors Rückkehr nach Erkundung] #auto
Viktor hebt den Blick und sieht nicht zu deinem Gesicht, sondern zu deinen Schuhen, als könne der Gang Staub genug verraten.
„Und?“, fragt er. „Reicht der Zug weiter, als er sollte?“
@@ -158,7 +158,7 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_insightful)
-> TURN
* {state_reached(mirror_started)} {state_before(mirror_done)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr ohne Spiegel] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(mirror_started) && state_before(mirror_done))} [AUTO: Viktors Rückkehr ohne Spiegel] #auto
Viktor hebt den Blick. Dein Hut sitzt wie zuvor, dein Gesicht auch.
„Der Spiegel war offenbar streng“, sagt er.
@@ -167,14 +167,14 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_closed)
-> TURN
* {state_reached(mirror_done)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach Spiegel] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(mirror_done))} [AUTO: Viktors Rückkehr nach Spiegel] #auto
Viktor hebt den Blick. Der Hut sitzt fester, die Nadeln besser, und dein Gesicht ist wieder die Fassung, in der Fremde es lesen sollen.
„Gut“, sagt er. Nicht schön, nicht besser. Gut. Ein dienstliches Urteil über eine gesellschaftliche Oberfläche.
~ rel_inc(viktor_reliable)
-> TURN
* {state_reached(privacy_started)} {state_before(privacy_taken)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr ohne Augenblick allein] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(privacy_started) && state_before(privacy_taken))} [AUTO: Viktors Rückkehr ohne Augenblick allein] #auto
Viktor hebt den Blick. Du bist gegangen, um Aufsicht loszuwerden, und warst doch kaum lange genug fort, um sie wirklich abzuschütteln.
„Hat der Augenblick genügt?“
@@ -183,14 +183,14 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_insightful)
-> TURN
* {state_reached(privacy_taken)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach privatem Augenblick] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(privacy_taken))} [AUTO: Viktors Rückkehr nach privatem Augenblick] #auto
Viktor hebt den Blick. Für eine kleine Weile gehörte dein Gesicht nur dir. Das merkt er, und weil er nicht dumm ist, benennt er es nicht.
„Wir fahren noch“, sagt er nur.
~ rel_inc(viktor_open)
-> TURN
* {state_reached(unwell_started)} {state_before(unwell_managed)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach Unwohlsein] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(unwell_started) && state_before(unwell_managed))} [AUTO: Viktors Rückkehr nach Unwohlsein] #auto
Viktor hebt den Blick. Die Sorge kommt schneller als sein Misstrauen.
„Setzen Sie sich“, sagt er. „Langsam.“
@@ -199,7 +199,7 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ rel_inc(viktor_open)
-> TURN
* {state_reached(unwell_managed)} {claim_choice_gate(return_auto)} [AUTO: Viktors Rückkehr nach Erleichterung] #auto:return(2)
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(unwell_managed))} [AUTO: Viktors Rückkehr nach Erleichterung] #auto
Viktor hebt den Blick, prüft deinen Gang und lässt die Frage in der Mappe verschwinden, aus der sie nie ganz herauskam.
„Besser?“, fragt er.
@@ -253,119 +253,14 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
-> TURN
+ (asked_viktor_role) {has(class_def)}
{lacks(route_language_def)} [__Stelle Viktor__: Wegen seiner Rolle zur Rede.]
~ state_reach(ViktorRelationFrame.escort_present)
~ state_reach(ViktorRelationFrame.secretary_cover_understood)
{lacks(route_language_def)} [__Prüfe Viktor__: Welche Aufgabe haben Sie wirklich, Herr Nowak?“]
-> viktor_role_dialogue ->
-> TURN
{tutorial(tut_dialog_intro):
#alert[Steht eine Entscheidung in Anführungszeichen, spricht Valerie diese Zeile aus. Das hervorgehobene Verb benennt die soziale Bewegung der Antwort.]
}
Viktor legt den Vordruck zurück in die Mappe. Du lässt ihm einen Augenblick, den Riemen zu schließen, und nimmst ihm dann die Bequemlichkeit, nur Sekretär zu sein.
* * [__Wahre Form__: „Welche Zeile betrifft Sie, Herr Nowak?“]
„Welche Zeile betrifft Sie, Herr Nowak?“
~ route_inc(route_composure)
~ rel_inc(viktor_reliable)
~ rel_inc(viktor_closed)
Er sieht dich an, als habe er gehofft, du würdest höflicher ausweichen. „Auf dem Papier: Sekretär. In der Praxis: Begleitung.“
* * [__Prüfe__: „Wer hat angeordnet, dass ich nicht allein reise?“]
„Wer hat angeordnet, dass ich nicht allein reise?“
~ route_inc(route_detective)
~ rel_inc(viktor_insightful)
~ rel_inc(viktor_bold)
„Die Stelle, die vermeiden möchte, dass diese Reise nach einer Anordnung aussieht.“
* * [__Entwaffne__: „Soll ich Sie Sekretär nennen, damit wir beide uns wohler fühlen?“]
„Soll ich Sie Sekretär nennen, damit wir beide uns wohler fühlen?“
~ route_inc(route_lover)
~ rel_inc(viktor_open)
~ rel_inc(viktor_unreliable)
„Mich macht das Wort nicht wohler“, sagt er. „Aber es macht andere Leute weniger aufmerksam.“
* * [__Schütze dich__: „Wessen Sicherheit meinen Sie, wenn Sie von meiner Begleitung sprechen?“]
„Wessen Sicherheit meinen Sie, wenn Sie von meiner Begleitung sprechen?“
~ route_inc(route_sapphic)
~ rel_inc(viktor_closed)
~ rel_inc(viktor_insightful)
Er antwortet nicht sofort. „Ihre. Die der Gastgeber. Und, falls die Berichte stimmen, die der Menschen, die nicht gefragt wurden.“
* * [__Verplappere dich__: „Ich weiß nicht, ob ich einen Sekretär, einen Wächter oder einen Zeugen vor mir habe.“]
„Ich weiß nicht, ob ich einen Sekretär, einen Wächter oder einen Zeugen vor mir habe.“
~ route_inc(route_careless)
~ rel_inc(viktor_unreliable)
~ rel_inc(viktor_passive)
Etwas an seiner Aufmerksamkeit wird vorsichtiger. „Das ist immerhin näher an der Wahrheit als Sekretär.“
* * [__Benenne__: „Sie reisen mit, damit Wien später sagen kann, es habe aufgepasst.“]
„Sie reisen mit, damit Wien später sagen kann, es habe aufgepasst.“
~ route_inc(route_eccentric)
~ rel_inc(viktor_bold)
~ rel_inc(viktor_adversarial)
„Wien sagt vieles später“, sagt Viktor. „Meistens mit saubereren Händen als vorher.“
-
~ mark(route_language_def)
~ state_reach(ValerieWorkingMask.social_strategy_established)
-> briefing
- (briefing)
~ state_reach(ViktorRelationFrame.handler_role_understood)
Viktor öffnet die Mappe und nimmt ein Memorandum heraus. Diesmal behält er es nicht bei sich, sondern legt es so vor dich, dass du lesen kannst. #gloss[Memorandum](Amtliche Denkschrift. Lang genug, um Zuständigkeit zu behaupten, kurz genug, um gefährliche Dinge nicht beim Namen nennen zu müssen.)
„Beim Umstieg erwartet uns eine Kutsche aus Hohenreith“, sagt er. „Ihren Gastgebern wurde mitgeteilt, ich sei Ihnen bei Korrespondenz, Reiseangelegenheiten und praktischen Vorkehrungen behilflich. Mehr müssen sie vorerst nicht wissen.“ #gloss[Korrespondenz](Briefwechsel. Die vornehme Kunst, Absichten so lange zu falten, bis sie in ein Kuvert passen.)
* * [__Präzisiere__: „Was wissen sie, was vermuten sie, und was soll ich prüfen dürfen?“]
„Was wissen sie, was vermuten sie, und was soll ich prüfen dürfen?“
~ route_inc(route_detective)
~ rel_inc(viktor_reliable)
„Sie wissen, dass Sie empfohlen kommen. Sie vermuten, dass Sie Störungen ohne Polizei, Priester oder Presse beilegen könnten. Ihnen ist gestattet, Betrug, Zwang, Gefährdung der öffentlichen Ordnung oder glaubwürdige, derzeit nicht einzuordnende Erscheinungen zu prüfen.“
* * [__Spotte__: „Wie fürsorglich. Der Staat erspart ihnen die Wörter.“]
„Wie fürsorglich. Der Staat erspart ihnen die Wörter.“
~ route_inc(route_eccentric)
~ rel_inc(viktor_adversarial)
„Der Staat erspart Unruhe, wenn er kann“, sagt Viktor. „Oder verteilt sie wenigstens an die richtigen Personen.“
* * [__Wahre Form__: „Die Familie bekommt eine Dame. Die Akten bekommen eine Konsultation. Sie bekommen Spielraum.“]
„Die Familie bekommt eine Dame. Die Akten bekommen eine Konsultation. Sie bekommen Spielraum.“
~ route_inc(route_composure)
~ rel_inc(viktor_reliable)
„Eine Zusammenfassung, die ich nicht unterschreiben würde. Aber ich würde ihr nicht widersprechen.“
-
~ state_reach(CourtMission.household_affair_named)
~ state_reach(CourtMission.supernatural_pretext_named)
Das Memorandum ist nicht lang. Es nennt nur, was für die Reise nötig ist.
Ein gräflicher Haushalt. Ein Jagdhaus in der Obersteiermark, nicht der Hauptsitz der Familie. Berichte über Störungen unter Dienerschaft und Dorfbewohnern. Kein Einschreiten der Polizei erbeten. Keine öffentliche kirchliche Untersuchung erwünscht. Keine Presse. Deine Anwesenheit ist als diskrete Konsultation auf Wunsch der Familie zu erklären. Herr Nowak dient zur Unterstützung praktischer Angelegenheiten. #gloss[Jagdhaus](Adeliger Landsitz für Jagden und kurze Aufenthalte. Weniger Hauptsitz als Bühne für Gäste, Förster, Gewehre und Geheimnisse.) #gloss[Obersteiermark](Der gebirgige Norden der Steiermark. Wälder, Eisen, enge Täler und ein Wetter, das sich nicht für Wiener Empfindlichkeiten interessiert.) #gloss[Dienerschaft](Die Bediensteten eines Hauses. Offiziell Teil der Ordnung, praktisch ihr Gedächtnis.)
* * [__Entlarve__: „Das ist nicht die ganze Weisung.“]
„Das ist nicht die ganze Weisung.“
~ route_inc(route_detective)
~ rel_inc(viktor_insightful)
Viktor fragt nicht, woher du es weißt. „Es gibt immer noch eine weitere Weisung.“
* * [__Benenne__: „Wien vertraut uns beiden so wenig, dass es Misstrauen aufteilen musste.“]
„Wien vertraut uns beiden so wenig, dass es Misstrauen aufteilen musste.“
~ route_inc(route_eccentric)
~ rel_inc(viktor_adversarial)
Viktor fragt nicht, woher du es weißt. „Es gibt immer noch eine weitere Weisung.“
* * [__Zügle dich__: „Dann behalten Sie sie. Ich werde merken, wann sie zwischen uns steht.“]
„Dann behalten Sie sie. Ich werde merken, wann sie zwischen uns steht.“
~ route_inc(route_composure)
~ rel_inc(viktor_reliable)
„Das halte ich für wahrscheinlich.“
-
~ state_reach(CourtMission.hidden_instruction_revealed)
~ state_reach(ViktorRelationFrame.skepticism_registered)
-> train_compartment
+ {state_reached(dining_car_seen)}
{meal(meal_unset)} [__Schlage Viktor vor__: „Wir könnten im Speisewagen essen.“]
-> dining_plan_dialogue ->
-> TURN
* (read_hohenreith_request) {has(class_def)}
{lacks(belief_def)} [__Verlange__: Zu sehen, weshalb du gerufen wurdest.]
@@ -414,30 +309,149 @@ Für alle Fremden ist er nun dein Sekretär. Er öffnet Türen, trägt Gepäck,
~ mark(belief_def)
-> train_compartment
+ {state_reached(dining_car_seen)}
{meal(meal_unset)} [__Schlage vor__: Die Mittagsfrage zu klären.]
-> DONE
=== dining_plan_dialogue ===
„Wir könnten im Speisewagen essen.“
„Beim Umstieg“, sagt Viktor, „wird Zeit sein, wenn wir sie nicht verlieren. Speisewagen, Bahnhofsrestauration oder nur etwas Kleines im Abteil. Alles spart etwas und kostet etwas.“ #gloss[Bahnhofsrestauration](Gastwirtschaft am Bahnhof. Reisezeit wird dort zu Suppe, Kaffee, Gedränge und sehr genauer Beobachtung von Gepäck und Stand.)
* * [__Wähle__: Jetzt mit Viktor in den Speisewagen zu gehen.]
* [__Wähle__: Jetzt mit Viktor in den Speisewagen zu gehen.]
~ meal_choose(dining_car)
~ companion_join(viktor)
Der Speisewagen ist kontrollierter als ein Bahnhof und öffentlicher als dieses Abteil. Man schaut dort mit Besteck in der Hand; das macht den Blick nicht freundlicher, nur gesellschaftsfähiger.
Viktor schließt die Mappe, steht auf und reicht dir nicht den Arm, sondern die Gelegenheit, ihn anzunehmen. Gemeinsam geht ihr in Fahrtrichtung durch die Wagen, bis der schmale Luxus des Speisewagens euch aufnimmt.
-> train_dining_car
-> train_dining_car_transition
* * [__Wähle__: Am Bahnhof zu essen.]
* [__Wähle__: Am Bahnhof zu essen.]
~ meal_choose(station_restaurant)
Der Bahnhof ist lauter, unsauberer, ehrlicher. Man erfährt selten mehr über eine Ordnung, als wenn sie Suppe bestellt, Trinkgeld gibt und auf die Uhr sieht.
* * [__Wähle__: Nur Tee, Gebäck und Ruhe zu verlangen.]
* [__Wähle__: Nur Tee, Gebäck und Ruhe zu verlangen.]
~ meal_choose(light_refreshment)
Du sparst Zeit, nicht Erschöpfung. Der Körper führt über solche Rechnungen eigene Bücher, und er ist selten nachsichtig.
-
-> train_compartment
->->
-> DONE
=== viktor_role_dialogue ===
~ state_reach(ViktorRelationFrame.escort_present)
~ state_reach(ViktorRelationFrame.secretary_cover_understood)
{tutorial(tut_dialog_intro):
#alert[Steht eine Entscheidung in Anführungszeichen, spricht Valerie diese Zeile aus. Das hervorgehobene Verb benennt die soziale Bewegung der Antwort.]
}
„Welche Aufgabe haben Sie wirklich, Herr Nowak?“
Viktor legt den Vordruck zurück in die Mappe. Du lässt ihm einen Augenblick, den Riemen zu schließen, und nimmst ihm dann die Bequemlichkeit, nur Sekretär zu sein.
* [__Wahre Form__: „Welche Zeile betrifft Sie, Herr Nowak?“]
„Welche Zeile betrifft Sie, Herr Nowak?“
~ route_inc(route_composure)
~ rel_inc(viktor_reliable)
~ rel_inc(viktor_closed)
Er sieht dich an, als habe er gehofft, du würdest höflicher ausweichen. „Auf dem Papier: Sekretär. In der Praxis: Begleitung.“
* [__Prüfe__: „Wer hat angeordnet, dass ich nicht allein reise?“]
„Wer hat angeordnet, dass ich nicht allein reise?“
~ route_inc(route_detective)
~ rel_inc(viktor_insightful)
~ rel_inc(viktor_bold)
„Die Stelle, die vermeiden möchte, dass diese Reise nach einer Anordnung aussieht.“
* [__Entwaffne__: „Soll ich Sie Sekretär nennen, damit wir beide uns wohler fühlen?“]
„Soll ich Sie Sekretär nennen, damit wir beide uns wohler fühlen?“
~ route_inc(route_lover)
~ rel_inc(viktor_open)
~ rel_inc(viktor_unreliable)
„Mich macht das Wort nicht wohler“, sagt er. „Aber es macht andere Leute weniger aufmerksam.“
* [__Schütze dich__: „Wessen Sicherheit meinen Sie, wenn Sie von meiner Begleitung sprechen?“]
„Wessen Sicherheit meinen Sie, wenn Sie von meiner Begleitung sprechen?“
~ route_inc(route_sapphic)
~ rel_inc(viktor_closed)
~ rel_inc(viktor_insightful)
Er antwortet nicht sofort. „Ihre. Die der Gastgeber. Und, falls die Berichte stimmen, die der Menschen, die nicht gefragt wurden.“
* [__Verplappere dich__: „Ich weiß nicht, ob ich einen Sekretär, einen Wächter oder einen Zeugen vor mir habe.“]
„Ich weiß nicht, ob ich einen Sekretär, einen Wächter oder einen Zeugen vor mir habe.“
~ route_inc(route_careless)
~ rel_inc(viktor_unreliable)
~ rel_inc(viktor_passive)
Etwas an seiner Aufmerksamkeit wird vorsichtiger. „Das ist immerhin näher an der Wahrheit als Sekretär.“
* [__Benenne__: „Sie reisen mit, damit Wien später sagen kann, es habe aufgepasst.“]
„Sie reisen mit, damit Wien später sagen kann, es habe aufgepasst.“
~ route_inc(route_eccentric)
~ rel_inc(viktor_bold)
~ rel_inc(viktor_adversarial)
„Wien sagt vieles später“, sagt Viktor. „Meistens mit saubereren Händen als vorher.“
-
~ mark(route_language_def)
~ state_reach(ValerieWorkingMask.social_strategy_established)
-> briefing
= briefing
~ state_reach(ViktorRelationFrame.handler_role_understood)
Viktor öffnet die Mappe und nimmt ein Memorandum heraus. Diesmal behält er es nicht bei sich, sondern legt es so vor dich, dass du lesen kannst. #gloss[Memorandum](Amtliche Denkschrift. Lang genug, um Zuständigkeit zu behaupten, kurz genug, um gefährliche Dinge nicht beim Namen nennen zu müssen.)
„Beim Umstieg erwartet uns eine Kutsche aus Hohenreith“, sagt er. „Ihren Gastgebern wurde mitgeteilt, ich sei Ihnen bei Korrespondenz, Reiseangelegenheiten und praktischen Vorkehrungen behilflich. Mehr müssen sie vorerst nicht wissen.“ #gloss[Korrespondenz](Briefwechsel. Die vornehme Kunst, Absichten so lange zu falten, bis sie in ein Kuvert passen.)
* [__Präzisiere__: „Was wissen sie, was vermuten sie, und was soll ich prüfen dürfen?“]
„Was wissen sie, was vermuten sie, und was soll ich prüfen dürfen?“
~ route_inc(route_detective)
~ rel_inc(viktor_reliable)
„Sie wissen, dass Sie empfohlen kommen. Sie vermuten, dass Sie Störungen ohne Polizei, Priester oder Presse beilegen könnten. Ihnen ist gestattet, Betrug, Zwang, Gefährdung der öffentlichen Ordnung oder glaubwürdige, derzeit nicht einzuordnende Erscheinungen zu prüfen.“
* [__Spotte__: „Wie fürsorglich. Der Staat erspart ihnen die Wörter.“]
„Wie fürsorglich. Der Staat erspart ihnen die Wörter.“
~ route_inc(route_eccentric)
~ rel_inc(viktor_adversarial)
„Der Staat erspart Unruhe, wenn er kann“, sagt Viktor. „Oder verteilt sie wenigstens an die richtigen Personen.“
* [__Wahre Form__: „Die Familie bekommt eine Dame. Die Akten bekommen eine Konsultation. Sie bekommen Spielraum.“]
„Die Familie bekommt eine Dame. Die Akten bekommen eine Konsultation. Sie bekommen Spielraum.“
~ route_inc(route_composure)
~ rel_inc(viktor_reliable)
„Eine Zusammenfassung, die ich nicht unterschreiben würde. Aber ich würde ihr nicht widersprechen.“
-
~ state_reach(CourtMission.household_affair_named)
~ state_reach(CourtMission.supernatural_pretext_named)
Das Memorandum ist nicht lang. Es nennt nur, was für die Reise nötig ist.
Ein gräflicher Haushalt. Ein Jagdhaus in der Obersteiermark, nicht der Hauptsitz der Familie. Berichte über Störungen unter Dienerschaft und Dorfbewohnern. Kein Einschreiten der Polizei erbeten. Keine öffentliche kirchliche Untersuchung erwünscht. Keine Presse. Deine Anwesenheit ist als diskrete Konsultation auf Wunsch der Familie zu erklären. Herr Nowak dient zur Unterstützung praktischer Angelegenheiten. #gloss[Jagdhaus](Adeliger Landsitz für Jagden und kurze Aufenthalte. Weniger Hauptsitz als Bühne für Gäste, Förster, Gewehre und Geheimnisse.) #gloss[Obersteiermark](Der gebirgige Norden der Steiermark. Wälder, Eisen, enge Täler und ein Wetter, das sich nicht für Wiener Empfindlichkeiten interessiert.) #gloss[Dienerschaft](Die Bediensteten eines Hauses. Offiziell Teil der Ordnung, praktisch ihr Gedächtnis.)
* [__Entlarve__: „Das ist nicht die ganze Weisung.“]
„Das ist nicht die ganze Weisung.“
~ route_inc(route_detective)
~ rel_inc(viktor_insightful)
Viktor fragt nicht, woher du es weißt. „Es gibt immer noch eine weitere Weisung.“
* [__Benenne__: „Wien vertraut uns beiden so wenig, dass es Misstrauen aufteilen musste.“]
„Wien vertraut uns beiden so wenig, dass es Misstrauen aufteilen musste.“
~ route_inc(route_eccentric)
~ rel_inc(viktor_adversarial)
Viktor fragt nicht, woher du es weißt. „Es gibt immer noch eine weitere Weisung.“
* [__Zügle dich__: „Dann behalten Sie sie. Ich werde merken, wann sie zwischen uns steht.“]
„Dann behalten Sie sie. Ich werde merken, wann sie zwischen uns steht.“
~ route_inc(route_composure)
~ rel_inc(viktor_reliable)
„Das halte ich für wahrscheinlich.“
-
~ state_reach(CourtMission.hidden_instruction_revealed)
~ state_reach(ViktorRelationFrame.skepticism_registered)
->->
=== train_compartment_entry ===
@@ -668,9 +682,6 @@ Im nächsten Wagen riecht der Gang stärker nach Kohle, feuchter Wolle und kalte
Das Schild ist klein, emailliert und sachlich. Es verspricht nichts als Wasser, Spiegel und Verriegelung. Gerade deshalb wirkt es in diesem Zug beinahe intim.
-> TURN
* [__Prüfe__: Die Tür zum Speisewagen.]
Durch das Glas in Fahrtrichtung blitzt gelegentlich Weiß auf: Tücher, Hemdmanschetten, ein Kellnerärmel. Der Speisewagen ist kein Raum, den man zufällig betritt. Man erscheint dort, und dieses Erscheinen braucht eine Begründung.
-> TURN
-> DONE
@@ -696,11 +707,8 @@ Der dritte Wagen ist praktischer gebaut. Türen stehen enger, der Boden antworte
~ state_reach_if_started(unwell_managed)
-> train_washroom
+ {state_before(dining_car_seen)} [__Sieh nach__: Was hinter der Tür in Fahrtrichtung liegt. #key:s]
~ state_reach(dining_car_seen)
~ state_reach_if_started(explore_train_done)
Du öffnest die Tür in Fahrtrichtung nur weit genug, um hineinzusehen. Dahinter liegt der Speisewagen: weiße Tücher, Glas, Besteck, Kellner mit ruhigen Händen. Allein weiterzugehen wäre auffällig; mit Viktor wäre es eine Mahlzeit.
-> TURN
+ [__Öffne__: Die Tür in Fahrtrichtung. #key:s]
-> train_dining_car_transition
-> DONE
@@ -708,6 +716,27 @@ Der dritte Wagen ist praktischer gebaut. Türen stehen enger, der Boden antworte
// ROOM: DINING CAR
// ============================================================================
=== train_dining_car_transition ===
{
- state_before(dining_car_seen):
~ state_reach(dining_car_seen)
~ state_reach_if_started(explore_train_done)
Du öffnest die Tür in Fahrtrichtung nur weit genug, um hineinzusehen. Dahinter liegt der Speisewagen: weiße Tücher, Glas, Besteck, Kellner mit ruhigen Händen. Allein weiterzugehen wäre auffällig; mit Viktor wäre es eine Mahlzeit.
}
{
- not present(viktor):
Der Speisewagen ist kein Raum, den man zufällig betritt. Man erscheint dort, und dieses Erscheinen braucht eine Begründung. Ohne Viktor wäre es Neugier. Mit ihm könnte es Mittagessen sein.
-> TURN
- else:
{loc(loc_train_compartment):
Ihr geht in Fahrtrichtung durch den ersten Korridor, über die schwankenden Verbindungen, vorbei an Abteiltüren, Waschraumschild und blanken Griffen. Der Speisewagen wartet nicht, aber er nimmt euch auf, als hätte er euch erwartet.
- else:
Viktor öffnet die Tür in Fahrtrichtung für dich. Aus der Grenze wird ein Auftritt: Tischtücher, Glas, Kellnerhände und der kurze prüfende Blick jener Reisenden, die ihr Essen für Privatheit halten.
}
-> train_dining_car
}
=== train_dining_car ===
-> enter_room(loc_train_dining_car, -> train_dining_car_entry, -> train_dining_car_look, -> train_dining_car_exits, -> train_dining_car_bucket) -> TURN
@@ -787,7 +816,7 @@ Der Speisewagen ist schmaler Luxus in Bewegung: Tische mit zu weißen Tüchern,
=== train_dining_car_exits ===
+ {present(viktor)} [__Beende__: Das Essen und kehre mit Viktor ins Abteil zurück. #key:n]
Der Speisewagen entlässt euch mit Glasgeräusch und Kohlenrauch. Ihr geht gegen die Fahrtrichtung zurück, durch den praktischen Wagen, den zweiten Wagen und den ersten Korridor, bis Viktor die Tür zu eurem Abteil öffnet.
~ character_move_to(viktor, loc_train_compartment)
~ loc_move_to(loc_train_compartment)
~ companion_leave(viktor)
-> train_compartment
-> DONE
+2 -1
View File
@@ -20,8 +20,9 @@
=== station_midday ===
~ state_reach(meal_plan_chosen)
~ character_move_to(viktor, loc_station_platform)
~ companion_join(viktor)
~ loc_move_to(loc_station_platform)
~ contact_sync()
Die Station ist klein genug, dass der Zug kurz verlegen wirkt, als er dort hält. #chapter[Der Bahnhof] #image[muerzzuschlag.png](portrait)
+2 -1
View File
@@ -23,8 +23,9 @@
=== carriage_ride ===
~ character_move_to(viktor, loc_carriage)
~ companion_join(viktor)
~ loc_move_to(loc_carriage)
~ contact_sync()
Die Kutsche lässt die Station hinter sich und damit das letzte leicht erkennbare Zeichen der Monarchie. #chapter[Die Kutschenfahrt] #music[Kaiserpunk Jodler.mp3](crossfade, loop, lead=4)
@@ -3877,9 +3877,9 @@ Komplexe Encounter sollen bevorzugt in mehrere parallele Progress-Tracker zerleg
Zusätzlich gibt es unabhängige Facts mit `mark`, `has` und `lacks`. Diese sind nur für zusammengehörige Gruppen einzelner Facts gedacht, die unabhängig voneinander wahr sein können und keine Reihenfolge implizieren, etwa Tutorial gesehen, Mahlzeit am Bahnhof genommen, öffentliche Form gewahrt oder beschädigt. Solche Facts sind keine Callbacks, solange sie nicht ein konkretes abgespieltes Contentstück ersetzen.
Für Choice-Surface-Arbitration gibt es `claim_choice_gate(gate)`. Dieser Helper ist kein Story-State. Er wird am Anfang jedes `provide_choices` zurückgesetzt und gibt innerhalb dieses einen Choice-Aufbaus nur beim ersten gültigen Claim für dasselbe Gate `true` zurück. Er wird verwendet, wenn mehrere Atome gleichzeitig gültig sein können, aber höchstens eines davon auf der Oberfläche erscheinen darf. Der wichtigste Fall sind priorisierte `#auto`-Familien wie Viktors Rückkehrkommentare.
Für Choice-Surface-Arbitration gibt es `claim_choice_gate_if(gate, available)`. Dieser Helper ist kein Story-State. Er wird am Anfang jedes `provide_choices` zurückgesetzt und gibt innerhalb dieses einen Choice-Aufbaus nur beim ersten gültigen Claim für dasselbe Gate `true` zurück. Er wird verwendet, wenn mehrere Atome gleichzeitig gültig sein können, aber höchstens eines davon auf der Oberfläche erscheinen darf. Der wichtigste Fall sind priorisierte `#auto`-Familien wie Viktors Rückkehrkommentare.
Die Reihenfolge der Atome im Bucket ist dann die Priorität. Auto-Choices werden vom Client getrennt behandelt, nicht randomisiert und wie normale Ink-Choices ausgelöst. Ein gemeinsamer Auto-Key wie `#auto:return(2)` taktet die Familie über mehrere Choice-Turns; `claim_choice_gate(return_auto)` verhindert mehrere Treffer im selben Choice-Aufbau. Der Gate-Claim steht immer als letzte Bedingung hinter den normalen Verfügbarkeitsbedingungen, damit eine falsche Kandidaten-Choice das Gate nicht verbraucht. Auf Choice-Zeilen wird für keyed Auto-Tags die Doppelpunktform verwendet, weil `#auto[return](2)` dort von Ink nicht akzeptiert wird.
Die Reihenfolge der Atome im Bucket ist dann die Priorität. Auto-Choices werden vom Client getrennt behandelt, nicht randomisiert und wie normale Ink-Choices ausgelöst. `claim_choice_gate_if(return_auto, available)` verhindert mehrere Treffer im selben Choice-Aufbau. Rückkehrkommentare müssen in ihrer `available`-Bedingung zusätzlich über den Contact Manager gegated werden, zum Beispiel mit `reunion(viktor)`. Die vollständige Verfügbarkeitsbedingung wird als zweiter Parameter übergeben, damit falsche Kandidaten das Gate nicht verbrauchen.
Regel: Wenn die spätere Zeile „du hast damals genau X getan“ bedeutet, ist es ein Callback und soll über ein Ink-Label laufen. Wenn sie „du wirkst auf mich inzwischen wie Y“ bedeutet, ist es eine Heuristik. Wenn sie „diese Wissens- oder Plotlinie ist jetzt mindestens so weit“ bedeutet, ist es ein Encounter State. Wenn sie „dieses unabhängige Ergebnis gilt“ bedeutet, ist es ein Fact. Wenn ein Vorgang auch nur begonnen und vollendet kennt, aber Vollendung den Beginn voraussetzt, ist es bereits ein Encounter State.
@@ -3892,15 +3892,30 @@ Nie zulässig:
## 12.5.2 Companion- und Privacy-Helfer
Für Dialoge, die nur ohne Zeugen oder nur mit einer bestimmten Begleitfigur auftauchen sollen:
Der Contact Manager in `helpers.ink` verwaltet, welche getrackten Figuren gerade anwesend sind, welche Valerie zum ersten Mal trifft, welche sie nach einer Trennung wieder sieht und welche gerade nicht mehr anwesend sind. Kapiteldateien dürfen dafür keine raumspezifischen Flags wie `viktor_returned_to_compartment` oder `seen_viktor_leave` anlegen.
`loc_move_to(location)` setzt Valeries Ort, bewegt alle Figuren in `companions` mit und aktualisiert danach den Kontaktzustand. `companion_join(character)` und `companion_leave(character)` steuern nur, ob eine Figur Valerie bei Traversal folgt. Sie sind keine Erinnerungsflags. Startpositionen von Figuren und die anfängliche Begleitung gehören in das Episode-Setup. Wenn ein Setup mehrere Figuren manuell platziert, wird danach `contact_sync()` verwendet, damit der Anfangszustand ohne künstliche Wiedersehens- oder Erstbegegnungsreaktion gesetzt ist.
Für Dialoge, die nur ohne Zeugen, nur mit einer bestimmten Begleitfigur oder nur direkt nach einem Kontaktwechsel auftauchen sollen:
```ink
{present(viktor): ...}
{first_meeting(viktor): ...}
{reunion(viktor): ...}
{parting(viktor): ...}
{alone(): ...}
{alone_with(viktor): ...}
```
`present(character)` prüft, ob die Figur im aktuellen Raum ist. `alone()` ist wahr, wenn keine getrackte Figur im Raum ist. `alone_with(character)` ist wahr, wenn genau diese Figur anwesend ist. Bei neuen getrackten Figuren muss die Helper-Implementierung erweitert werden, damit `alone()` und `alone_with()` nicht still zu eng bleiben.
`present(character)` prüft, ob die Figur im aktuellen Raum ist. `first_meeting(character)`, `reunion(character)` und `parting(character)` gelten nur für die erste Choice-Oberfläche direkt nach dem Kontaktwechsel. Der nächste Turn löscht diese Transitionen automatisch in `provide_choices`. Kapitelinhalt darf Contact-Transitionen nur abfragen, niemals manuell löschen oder verbrauchen.
```ink
+ {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(freshen_up_done))} [AUTO: Viktors Rückkehr nach Frischmachen] #auto
...
-> TURN
```
`alone()` ist wahr, wenn keine getrackte Figur im Raum ist. `alone_with(character)` ist wahr, wenn genau diese Figur anwesend ist. Bei neuen getrackten Figuren muss die Helper-Implementierung an einer Stelle erweitert werden, damit Presence, Contact Transitions und Privacy Checks gemeinsam korrekt bleiben.
## 12.6 Conditionals
+104 -11
View File
@@ -45,6 +45,14 @@ VAR current_episode_end = -> empty_bucket
VAR current_game_bucket = -> game_bucket
VAR claimed_choice_gates = ()
VAR contact_seen = ()
VAR contact_present = ()
VAR contact_arrived = ()
VAR contact_departed = ()
VAR contact_first_met = ()
VAR contact_rejoined = ()
VAR contact_transition_fresh = false
VAR slot_early_morning_episode = no_episode
VAR slot_mid_morning_episode = episode_train_intro
VAR slot_noon_episode = episode_station_midday
@@ -81,6 +89,12 @@ VAR slot_late_night_episode = no_episode
=== provide_choices ===
~ claimed_choice_gates = ()
{
- contact_transition_fresh:
~ contact_transition_fresh = false
- else:
~ contact_clear_transitions()
}
{
- room_seen_on_enter():
<- current_moment_bucket
<- current_room_look_bucket
@@ -107,11 +121,11 @@ VAR slot_late_night_episode = no_episode
// mark/has/lacks facts.
//
// Example:
// Put claim_choice_gate last in the condition list. Earlier conditions should
// prove that the choice is valid before this side-effecting helper consumes the
// gate.
// Use claim_choice_gate_if when the choice has any availability condition. Pass
// the whole availability expression as the second parameter so invalid choices
// cannot consume the gate while Ink is checking the surface.
//
// * {state_reached(freshen_up_done)} {claim_choice_gate(return_auto)} [...] #auto:return(2)
// * {claim_choice_gate_if(return_auto, reunion(viktor) && state_reached(freshen_up_done))} [...] #auto
=== function claim_choice_gate(gate) ===
{
- claimed_choice_gates ? gate:
@@ -121,6 +135,14 @@ VAR slot_late_night_episode = no_episode
~ return true
}
=== function claim_choice_gate_if(gate, available) ===
{
- not available:
~ return false
- else:
~ return claim_choice_gate(gate)
}
=== empty_bucket ===
-> DONE
@@ -517,10 +539,17 @@ VAR route_eccentric = 0
//
// Author-facing helpers:
// - loc(value), loc_is(value): true when Valerie is at location.
// - loc_move_to(value): move Valerie and all current companions to location.
// - loc_move_to(value): move Valerie and all current companions to location,
// then update the contact manager.
// - accompanied_by(character): true when character is in the companion list.
// - companion_join(character), companion_leave(character): update companions.
// - present(character): true when a character's location equals current_location.
// - first_meeting(character): true on the choice surface where Valerie meets
// that tracked character for the first time.
// - reunion(character): true on the choice surface where Valerie sees a known
// tracked character again after they were apart.
// - parting(character): true on the choice surface after a tracked character
// has just stopped being present.
// - alone(): true when no tracked NPC is currently present with Valerie.
// - alone_with(character): true when exactly the given tracked NPC is present.
// - character_move_to(character, location): move a known NPC independently.
@@ -532,6 +561,12 @@ VAR route_eccentric = 0
//
// Internal helper:
// - move_companions_to(location) is used by loc_move_to().
// - contact_update() refreshes first-meeting, reunion, and parting transitions.
// - contact_sync() establishes current contact without transitions, useful
// after episode setup that places multiple characters at once.
// - contact_clear_transitions() is called internally by provide_choices. Content
// must not consume or clear contact transitions manually.
// - characters_at(location) must be extended when a new tracked NPC is added.
// - room_seen_on_enter() is used by provide_choices() to decide whether to show
// the one-shot entry text or the repeat look action.
@@ -541,6 +576,7 @@ VAR route_eccentric = 0
=== function loc_move_to(value) ===
~ current_location = value
~ move_companions_to(value)
~ contact_update()
=== function loc_is(value) ===
~ return current_location == value
@@ -555,12 +591,16 @@ VAR route_eccentric = 0
~ companions -= character
=== function present(character) ===
{
- character == viktor:
~ return viktor_location == current_location
- else:
~ return false
}
~ return characters_at(current_location) ? character
=== function first_meeting(character) ===
~ return contact_first_met ? character
=== function reunion(character) ===
~ return contact_rejoined ? character
=== function parting(character) ===
~ return contact_departed ? character
=== function alone() ===
~ return not present(viktor)
@@ -578,6 +618,7 @@ VAR route_eccentric = 0
- character == viktor:
~ viktor_location = location
}
~ contact_update()
=== function move_companions_to(location) ===
{
@@ -585,6 +626,58 @@ VAR route_eccentric = 0
~ viktor_location = location
}
=== function characters_at(location) ===
~ temp result = ()
{
- viktor_location == location:
~ result += viktor
}
~ return result
=== function contact_sync() ===
~ contact_present = characters_at(current_location)
~ contact_seen += contact_present
~ contact_arrived = ()
~ contact_departed = ()
~ contact_first_met = ()
~ contact_rejoined = ()
~ contact_transition_fresh = false
=== function contact_update() ===
~ temp previous = contact_present
~ contact_present = characters_at(current_location)
~ contact_arrived = ()
~ contact_departed = ()
~ contact_first_met = ()
~ contact_rejoined = ()
{
- (contact_present ? viktor) && not (previous ? viktor):
~ contact_arrived += viktor
{
- contact_seen ? viktor:
~ contact_rejoined += viktor
- else:
~ contact_first_met += viktor
}
}
{
- (previous ? viktor) && not (contact_present ? viktor):
~ contact_departed += viktor
}
~ contact_seen += contact_present
~ contact_transition_fresh = false
{
- contact_arrived || contact_departed || contact_first_met || contact_rejoined:
~ contact_transition_fresh = true
}
=== function contact_clear_transitions() ===
~ contact_arrived = ()
~ contact_departed = ()
~ contact_first_met = ()
~ contact_rejoined = ()
~ contact_transition_fresh = false
=== enter_episode(value, slot, start_bucket, end_bucket, episode_bucket) ===
~ episode_start(value, slot)
~ current_episode_start = start_bucket
File diff suppressed because one or more lines are too long