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
Exceptiondefiniert, 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)" aliveist als abgeleitete Property modelliert, damit Konsistenz mithpgarantiert ist. beleg: " return self.hp > 0"- Optionale Felder wie
placementundlast_opponentwerden 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_levelfehlt. 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.shopvollstä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
returnab, 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
backend/tft/sim/player.py::grab_carousel_unit
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