Files
tft/.planer/einheiten/backend__tft__sim__player.py.md
2026-07-24 11:24:24 +02:00

11 KiB

Einheiten: backend/tft/sim/player.py

stand: f41ac76b57

backend/tft/sim/player.py::InvalidAction

beschreibung: Markiert ungültige Spielaktionen als Ausnahme. input: eine Fehlermeldung als Zeichenkette. output: eine Exception, die von Aufrufern abgefangen wird. entscheidungen:

  • Wird als eigene Exception-Klasse statt generischer Exception definiert, damit Aufrufer gezielt reagieren können. beleg: "class InvalidAction(Exception):"
  • Enthält bewusst keine eigene Logik, sondern dient nur als Typ-Marker. beleg: " pass" kanten:
  • wird-genutzt-von: backend/tft/sim/player.py::buy
  • wird-genutzt-von: backend/tft/sim/player.py::sell
  • wird-genutzt-von: backend/tft/sim/player.py::buy_xp
  • wird-genutzt-von: backend/tft/sim/player.py::move
  • wird-genutzt-von: backend/tft/sim/player.py::equip
  • wird-genutzt-von: backend/tft/sim/player.py::pick_augment

backend/tft/sim/player.py::PlayerState

beschreibung: Hält den kompletten Zustand eines Spielers über alle Runden hinweg. input: Initialwerte für Name, Archetyp, HP, Gold und Level. output: ein Datensatz-Objekt mit Board, Bench, Items, Augments und Shop. entscheidungen:

  • Verwendet field(default_factory=list) für mutable Defaults, um die geteilte-Liste-Falle zu vermeiden. beleg: " board: list = field(default_factory=list)"
  • alive ist als abgeleitete Property modelliert, damit Konsistenz mit hp garantiert ist. beleg: " return self.hp > 0"
  • Optionale Felder wie placement und last_opponent werden explizit typisiert, damit Phasen ohne Gegner sauber abgebildet werden. beleg: " placement: int | None = None" kanten:
  • nutzt: backend/tft/sim/player.py::score
  • wird-genutzt-von: backend/tft/sim/player.py::new_player

backend/tft/sim/player.py::new_player

beschreibung: Erzeugt einen frischen PlayerState aus einer Konfiguration. input: Name, Archetyp und ein Konfigurations-Dictionary. output: ein neu initialisierter PlayerState mit Startwerten. entscheidungen:

  • Liest Startwerte aus cfg, um Regelvarianten ohne Code-Änderung zu erlauben. beleg: " hp=cfg["damage"]["player_hp"],"
  • Fallback auf Level 1, falls start_level fehlt. beleg: " level=cfg["xp"].get("start_level", 1)," kanten:
  • ruft-auf: backend/tft/sim/player.py::PlayerState
  • nutzt: backend/tft/sim/player.py::PlayerState

backend/tft/sim/player.py::score

beschreibung: Berechnet die Spielstärke eines Spielers für die Schaden-Berechnung. input: ein Spielerzustand und ein Artifact-Dictionary. output: ein Float-Score des aktuellen Boards inklusive Augments. entscheidungen:

  • Delegiert die eigentliche Berechnung an score_board, um die Bewertungslogik zentral zu halten. beleg: " return score_board(p.board, p.augments, artifact)"
  • Bezieht Augments in den Score ein, damit gewählte Bonüsse kampfrelevant zählen. beleg: " return score_board(p.board, p.augments, artifact)" kanten:

backend/tft/sim/player.py::unit_worth

beschreibung: Liefert den ökonomischen Gegenwert einer Einheit für Aufstellungsentscheidungen. input: Artifact-Dictionary und eine Einheit mit api_name und stars. output: ein Float-Wert als Kombination aus Kosten und Sternen. entscheidungen:

  • Skaliert den Wert mit 3 ** (stars - 1), da Merge-Stufen das Vielfache an Einheiten ersetzen. beleg: " return artifact["static"]["units"][u["api_name"]]["cost"] * 3 ** (u["stars"] - 1)"
  • Liest Einheitenkosten aus den statischen Artifact-Daten, damit Balance-Anpassungen ohne Code-Change greifen. beleg: " return artifact["static"]["units"][u["api_name"]]["cost"] * 3 ** (u["stars"] - 1)" kanten:
  • wird-genutzt-von: backend/tft/sim/player.py::fill_board

backend/tft/sim/player.py::refresh_shop

beschreibung: Erneuert die Shop-Anzeige eines Spielers mit neuen Roll-Ergebnissen. input: Spielerzustand, Pool, Konfiguration und RNG. output: keine Rückgabe; der Shop des Spielers wird ersetzt. entscheidungen:

  • Überschreibt p.shop vollständig statt zu mischen, um das TFT-typische „neuer Roll" zu modellieren. beleg: " p.shop = roll(pool, p.level, cfg, rng)" kanten:
  • wird-genutzt-von: backend/tft/sim/player.py::reroll

backend/tft/sim/player.py::merge

beschreibung: Führt automatisch passende Einheiten gleicher Sternstufe zu höheren Sternen zusammen. input: Spielerzustand, API-Name und aktuelle Sternstufe. output: keine Rückgabe; Board und Bench werden konsolidiert. entscheidungen:

  • Iteriert mit while True, bis weniger als drei Kopien vorhanden sind. beleg: " while True:"
  • Übernimmt die Items der fusionierten Kopien auf die verbleibende Einheit. beleg: " keep["items"].extend(u["items"])"
  • Kürzt das Item-Inventar der behaltenen Einheit auf das maximale Limit. beleg: " keep["items"] = keep["items"][:MAX_ITEMS_PER_UNIT]"
  • Entfernt überschüssige Einheiten aus Board oder Bench je nach Herkunft. beleg: " (p.board if u in p.board else p.bench).remove(u)" kanten:
  • wird-genutzt-von: backend/tft/sim/player.py::buy
  • wird-genutzt-von: backend/tft/sim/player.py::grab_carousel_unit

backend/tft/sim/player.py::buy

beschreibung: Kauft eine Einheit aus dem Shop und legt sie auf die Bank. input: Spielerzustand, Shop-Slot, Pool und Artifact-Dictionary. output: keine Rückgabe; Bench und Pool werden verändert. entscheidungen:

  • Prüft Shop-Slot, Gold, Bank-Kapazität und Pool-Verfügbarkeit in dieser Reihenfolge, um Mehrfach-Meldungen pro Aktion zu vermeiden. beleg: " if not (0 <= slot < len(p.shop)) or p.shop[slot] is None:"
  • Leert den Shop-Slot nach erfolgreichem Kauf explizit. beleg: " p.shop[slot] = None"
  • Startet sofort einen Merge-Versuch auf Sternstufe 1, damit Käufe direkt stapeln. beleg: " merge(p, api, 1)" kanten:
  • ruft-auf: backend/tft/sim/player.py::merge
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::sell

beschreibung: Verkauft eine Einheit vom Board oder Bench und erstattet Gold und Items zurück. input: Spielerzustand, Ort, Index, Pool und Artifact-Dictionary. output: keine Rückgabe; Gold, Items und Pool werden aktualisiert. entscheidungen:

  • Berechnet die Anzahl der Pool-Copies exponentiell zur Sternstufe. beleg: " copies = 3 ** (u["stars"] - 1)"
  • Zieht 1 Gold ab, sobald die Einheit nicht 1 kostet und mindestens 2 Sterne hat. beleg: " if cost > 1 and u["stars"] >= 2:"
  • Gibt Items aus dem Inventar der Einheit in das Spieler-Inventar frei. beleg: " p.items.extend(u["items"])" kanten:
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::reroll

beschreibung: Würfelt den Shop gegen Gold neu aus. input: Spielerzustand, Pool, Konfiguration und RNG. output: keine Rückgabe; der Shop wird aktualisiert. entscheidungen:

  • Prüft Gold erst nach dem Lesen der Kosten, damit einheitliche Fehlermeldungen entstehen. beleg: " if p.gold < cost:"
  • Delegiert das eigentliche Neu-Würfeln an refresh_shop, um Logik-Duplikation zu vermeiden. beleg: " refresh_shop(p, pool, cfg, rng)" kanten:
  • ruft-auf: backend/tft/sim/player.py::refresh_shop
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::buy_xp

beschreibung: Kauft zusätzliche Erfahrungspunkte und aktualisiert das Level. input: Spielerzustand und Konfiguration. output: keine Rückgabe; Level und XP werden fortgeschrieben. entscheidungen:

  • Lehnt den Kauf ab, wenn das maximale Level bereits erreicht ist. beleg: " if p.level >= xp["max_level"]:"
  • Übergibt die XP-Berechnung an economy.apply_xp, damit Level-Schwellen zentral gepflegt werden. beleg: " p.level, p.xp = economy.apply_xp(p.level, p.xp, xp["buy_amount"], cfg)" kanten:
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::move

beschreibung: Verschiebt eine Einheit zwischen Bank und Kampf-Board. input: Spielerzustand, Richtung und Index. output: keine Rückgabe; Board oder Bench werden mutiert. entscheidungen:

  • Wählt Quell- und Ziel-Liste abhängig von der Richtung in einer Zeile. beleg: " src, dst = (p.bench, p.board) if where == "bench" else (p.board, p.bench)"
  • Prüft die Board-Kapazität gegen das aktuelle Level des Spielers, nicht gegen einen festen Maximalwert. beleg: " if dst is p.board and len(p.board) >= p.level:" kanten:
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::equip

beschreibung: Legt ein Item aus dem Inventar auf eine Board-Einheit und craftet bei passender Komponente. input: Spielerzustand, Item-Index, Board-Index und optionales Artifact. output: keine Rückgabe; Einheit und Inventar werden angepasst. entscheidungen:

  • Sortiert die beiden Komponenten vor dem Lookup, damit die Reihenfolge keine Rolle spielt. beleg: " crafted = recipes.get("|".join(sorted((held, new_item))))"
  • Bricht die Funktion mit return ab, sobald ein Rezept erfolgreich gecraftet wurde. beleg: " p.items.pop(item_idx)" beleg: " return" kanten:
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::pick_augment

beschreibung: Wählt einen Augment aus dem aktuellen Angebot des Spielers. input: Spielerzustand und Wahl-Index. output: keine Rückgabe; Augments-Liste wird erweitert und Angebot geleert. entscheidungen:

  • Lehnt die Aktion ab, wenn aktuell kein Angebot vorliegt. beleg: " if not p.augment_offer:"
  • Leert das Angebot nach der Auswahl, damit kein zweiter Pick möglich ist. beleg: " p.augment_offer = []" kanten:
  • nutzt: backend/tft/sim/player.py::InvalidAction

backend/tft/sim/player.py::grant_loot

beschreibung: Verteilt Loot-Belohnungen wie Komponenten und Gold an einen Spieler. input: Spielerzustand, Anzahl Komponenten, Gold, Artifact und RNG. output: keine Rückgabe; Inventar und Gold werden erhöht. entscheidungen:

  • Wählt die Item-Quelle in absteigender Priorität aus Komponenten- und Item-Pool. beleg: " pool = (artifact.get("component_pool") or artifact.get("item_pool")"
  • Erlaubt nur das Droppen von Komponenten, fertige Items entstehen ausschließlich durch Crafting. beleg: " # Loot droppt Komponenten; fertige Items entstehen nur durch Craften." kanten:
  • nutzt: backend/tft/sim/player.py::InvalidAction

beschreibung: Greift eine zufällige Karussell-Einheit und legt sie auf die Bank. input: Spielerzustand, Pool und RNG. output: keine Rückgabe; Bench und Pool werden verändert. entscheidungen:

  • Sammelt Kandidaten aus den Kostenstufen 1 bis 3, da Karussell-Einheiten günstig sind. beleg: " candidates = [a for c in (1, 2, 3) for a in pool.units_of_cost(c)]"
  • Überspringt den Greif, wenn die Bank voll ist, ohne Fehler zu werfen. beleg: " if candidates and len(p.bench) < BENCH_SIZE:"
  • Startet sofort einen Merge-Versuch, damit Drops direkt stapeln. beleg: " merge(p, api, 1)" kanten:
  • ruft-auf: backend/tft/sim/player.py::merge

backend/tft/sim/player.py::fill_board

beschreibung: Füllt freie Board-Plätze und tauscht stärkere Bank-Einheiten ein. input: Spielerzustand und Artifact-Dictionary. output: keine Rückgabe; Board und Bench werden umsortiert. entscheidungen:

  • Sortiert die Bank absteigend nach unit_worth, damit starke Einheiten vorne stehen. beleg: " p.bench.sort(key=lambda u: -unit_worth(artifact, u))"
  • Tauscht Board-Einheiten nur aus, wenn der Bank-Kandidat strikt stärker ist. beleg: " if unit_worth(artifact, best) > unit_worth(artifact, u):"
  • Bricht die Swap-Schleife ab, sobald die Bank leer ist. beleg: " if not p.bench:" kanten:
  • ruft-auf: backend/tft/sim/player.py::unit_worth