Files
geograsim/App/sims/logistik/balance-corridor.md
T
Adminator 79ac9dad84 Atlas: Deploy-Buendel vor Staustufen-Sprint
- Logistik: Musik-Player Playlist-Modus (5 Gruppen, 20 Tracks)
- Heli: End-Screen auf .ggs-endscreen, Mission-Bilder, Voice-Lines, Briefing-Audio
- Logistik: Layout-Tausch Auftraege+Fahrzeuge links, Karte rechts
- Logistik: Tier-1-Staedte ausgebaut, Auto-Timescale-Badge
- Logistik: Roadnet/Railnet Dijkstra-Routing, Balance-Updates
- Atlas: 5 Atlas-Inbox-Nachrichten (Cards-Pattern, DALL-E-Key, Musik-Playlists)
- Status-Updates Heli + Logistik

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 01:05:13 +02:00

6.6 KiB
Raw Blame History

Balance-Korridor (Regeln R-1, R-2, R-3)

Stand: 2026-04-24 Gilt für: Logistik Europa (Modul 11), Vorlage für andere Sim-Module

Dieses Dokument formalisiert den Balance-Anspruch („jedes Level muss man gewinnen UND verlieren können") als drei Regeln und beschreibt eine mechanische Methode, sie zu prüfen.


1. Anspruch

Ein Level ist balanciert, wenn:

  1. Der/die Bearbeiter:in Zeit zum Nachdenken hat, bevor sie ins Minus rutscht (R-1 Runway).
  2. Mit gutem Spiel gewinnen kann (R-2 Winnable).
  3. Mit schlechtem oder keinem Spiel verlieren kann (R-3 Loseable).

Keine der drei Bedingungen darf systematisch verfehlt werden — sonst ist das Level entweder Frustquelle (kann nur verlieren) oder Pseudo- Lernspiel (kann nur gewinnen, keine Konsequenz).


2. Regel R-1 — Startbudget-Runway

Bereits in level-progression.md §2 hergeleitet. Hier nur die Formel:

startBudget ≥ 1.5 × ( rentalCostPerDay × vehicleCount
                   + idleCostPerHour   × vehicleCount × 12 )

Interpretation: Anfangsbudget reicht für 1.5 Tage Operating ohne Einnahmen. Gibt Puffer für Fehltrip + strategische Entscheidung.


3. Regel R-2 — Winnable

Bei optimalem oder mindestens guten Spiel muss der Level spätestens beim dritten Versuch mit positivem End-Saldo gegenüber minTargetEarnings enden.

Formal (Median über 5 Seeds):

  • L1: runLevel(1, *, naive)successful: true AND endBalance startBudget ≥ +1.000 €
  • L1: runLevel(1, *, greedy)successful: true AND endBalance startBudget ≥ +2.000 €
  • L2: runLevel(2, *, greedy)successful: true AND endBalance startBudget ≥ 0
  • L2: runLevel(2, *, optimal)successful: true AND endBalance startBudget ≥ +5.000 €
  • L3: runLevel(3, *, optimal)successful: true AND endBalance startBudget ≥ 0

(Werte aus balance-matrix.md §3 übernommen.)

Was wir gerade messen können:

  • L1: ✓ naive, greedy, optimal laufen — alle prüfbar
  • L2: ✓ greedy + optimal laufen — prüfbar
  • L3: ✓ optimal läuft (Best-Net-Heuristik seit 2026-04-24) — prüfbar

optimal ist keine echte globale Optimierung (VRP-TW ist NP-hart), sondern eine Best-Net-Heuristik: pro Tick wird die (Contract, Vehicle)- Paarung mit maximalem erwarteten Netto ausgewählt (reward × 1.15 pickup-fare delivery-fare erwartete Verspätungsstrafe). Dominiert greedy in allen drei Leveln und reicht als Proxy für „gutes Spiel".


4. Regel R-3 — Loseable

Untätigkeit oder grobes Fehlspiel muss zuverlässig zum Verlieren führen, sonst ist das Level keine Lernsituation.

Formal (Median über 5 Seeds):

  • L1: runLevel(1, *, noop)successful: false AND endBalance < minTargetEarnings
  • L2: runLevel(2, *, noop)successful: false
  • L3: runLevel(3, *, noop)successful: false
  • L2: runLevel(2, *, naive)successful: false (zusätzlich gefordert: schlechte Disposition reicht nicht)
  • L3: runLevel(3, *, naive)successful: false
  • L3: runLevel(3, *, greedy)successful: false ODER knapp negativ

Implizite Anforderung: Auch ohne Untätigkeit muss der Schweregrad mit Level steigen. L3 darf nicht durch greedy lösbar sein (sonst ist es nur ein L2-Klon).


5. Aktuelle Verifikation (Stand 2026-04-24)

R-1 (mathematisch)

Level Required ≥ Hat Verdikt
L1 0 8.000
L2 1.170 5.000
L3 4.650 5.000 (nach Fix vom 2026-04-24)

R-2 / R-3 (per Headless-Runner — siehe headless-runner.html)

Status: VOLLSTAENDIG
- noop, naive, greedy, optimal laufen alle
- Korridor-Check-Button in headless-runner.html pruft R-1 + R-2 + R-3
  ueber alle 60 Durchlaeufe (3 Lvl × 4 Strategien × 5 Seeds)

Konkrete Runs noch ausständig — beim Server-/Browser-Test mit headless-runner.html „Balance-Korridor-Check"-Button drücken (kommt mit dem Patch dieses Dokuments).


6. Methode zur Sicherstellung („was tun, wenn ein Level neu konfiguriert wird")

6a. Pre-Deploy-Check (vor jeder Level-Param-Änderung)

  1. R-1 mit Taschenrechner: Formel oben rechnen, muss ≥ erfüllt sein. Engine-seitig schon eingebaut: _validateRuleR1 in loadContent loggt console.warn bei Verletzung.
  2. R-2/R-3 via Headless-Runner: headless-runner.html öffnen, „Balance-Korridor-Check" drücken. Ergebnis-Tabelle vergleichen mit Soll-Korridor (siehe §3 + §4).
  3. Bei Verletzung: Param ändern (üblicherweise startBudget, minTargetEarnings, eventProbabilityMultiplier), erneut prüfen.
  4. Erst dann committen.

6b. Continuous Verification (perspektivisch, sobald Atlas freigibt)

  • Test-Suite-Script (Node.js): npm run balance-check führt LogistikRunner.runMatrix({levels:[1,2,3], strategies:[...], seeds:[1..5]}) und vergleicht gegen Korridor. Exit-Code 0 = pass, 1 = fail.
  • CI-Hook beim Push: blockiert Merge, wenn Korridor nicht erreicht.
  • Voraussetzung: Node-Engine-Export (engine.js läuft schon UMD-konform).

6c. Manueller Sanity-Check (ergänzend)

Reine Zahlen reichen nicht — der „Spielspaß" ist nicht messbar. Nach jedem Param-Change zusätzlich:

  • 1× Live-Test im Browser pro Level mit naive Spielstil (mehrere Fehltrips).
  • 1× Test mit gezielt-strategischem Spielstil.
  • Fühlt sich der Schwierigkeitsgrad richtig an, oder kommt Frust auf?

Die mechanischen Regeln R-1/R-2/R-3 sind notwendig, aber nicht hinreichend.


7. Offene Punkte

Kurzfristig (vor dem Schul-Pilot)

  • optimal-Strategie als Best-Net-Heuristik implementiert (2026-04-24, headless-runner.js, 120 Zeilen). Kriterium pro Tick: max reward × 1.15 pickup-fare delivery-fare erwartete Strafe, dann feasible Zuweisungen in Sortierreihenfolge feuern.
  • „Balance-Korridor-Check"-Button in headless-runner.html einbauen (erledigt, prueft R-1/R-2/R-3 mechanisch).

Mittelfristig

  • Node-Test-Script mit Exit-Code für CI.
  • Per-Modul-Generalisierung: das Korridor-Pattern in App/docs/integration-konzept.md als Plattform-Vertrag dokumentieren, damit jedes Modul (Klima, Heli, …) die gleiche Disziplin hat.

Langfristig

  • Stochastische Robustheit: Korridor nicht nur über 5 Seeds prüfen, sondern Konfidenzintervall (z.B. 95 % über 100 Seeds). Aktuell nicht nötig — die Engine ist deterministisch und 5 Seeds geben uns schon eine gute Stichprobe.