Files
tft/backend/tft/sim/combat.py
2026-07-23 00:35:30 +02:00

28 lines
1.0 KiB
Python

"""Combat = score comparison. Relative score difference -> win probability -> damage."""
import math
import random
def win_probability(score_a: float, score_b: float, cfg: dict) -> float:
mean = (score_a + score_b) / 2
if mean <= 0:
return 0.5
d = (score_a - score_b) / mean
return 1 / (1 + math.exp(-d / cfg["combat"]["tau"]))
def resolve(score_a: float, score_b: float, cfg: dict, rng: random.Random) -> bool:
"""True if A wins. Adds noise on top of the probability."""
noise = rng.gauss(0, cfg["combat"]["variance"])
return rng.random() < min(max(win_probability(score_a, score_b, cfg) + noise, 0.02), 0.98)
def damage(stage: int, winner_score: float, loser_score: float, winner_units: int, cfg: dict) -> int:
d = cfg["damage"]
base = d["stage_base"][min(stage - 1, len(d["stage_base"]) - 1)]
mean = (winner_score + loser_score) / 2 or 1
margin = abs(winner_score - loser_score) / mean
surviving = max(1, round(winner_units * min(margin, 1.0)))
return base + d["per_surviving_unit"] * surviving