73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
"""The one board-scoring entry point. Sim, bots, calibration, and UI all call this."""
|
|
|
|
from tft.model import baseline
|
|
|
|
|
|
def active_trait_tiers(board_units: list[dict], static_traits: dict, static_units: dict) -> dict:
|
|
"""trait api_name -> reached breakpoint ordinal (1-based), only active traits."""
|
|
counts: dict[str, int] = {}
|
|
for u in board_units:
|
|
unit = static_units.get(u["api_name"])
|
|
if not unit:
|
|
continue
|
|
for trait in set(unit["traits"]):
|
|
counts[trait] = counts.get(trait, 0) + 1
|
|
|
|
tiers = {}
|
|
for trait, n in counts.items():
|
|
info = static_traits.get(trait)
|
|
if not info:
|
|
continue
|
|
ordinal = 0
|
|
for i, bp in enumerate(info["breakpoints"], start=1):
|
|
if n >= bp["min_units"]:
|
|
ordinal = i
|
|
if ordinal:
|
|
tiers[trait] = ordinal
|
|
return tiers
|
|
|
|
|
|
def score_board(board_units: list[dict], augments: list[str], artifact: dict) -> float:
|
|
"""board_units: [{api_name, stars, items: [item api names]}]."""
|
|
static_units = artifact["static"]["units"]
|
|
static_traits = artifact["static"]["traits"]
|
|
learned = artifact.get("learned", {})
|
|
item_mults = learned.get("items", {})
|
|
trait_mults = learned.get("traits", {})
|
|
augment_mults = learned.get("augments", {})
|
|
pair_lifts = learned.get("pairs", {})
|
|
roles = artifact.get("roles", {})
|
|
|
|
total = 0.0
|
|
for u in board_units:
|
|
unit = static_units.get(u["api_name"])
|
|
if not unit:
|
|
continue
|
|
value = baseline.unit_value(unit["cost"], u["stars"])
|
|
role = roles.get(u["api_name"]) or baseline.classify_role(unit)
|
|
for item in u.get("items", []):
|
|
mult = item_mults.get(item, baseline.DEFAULT_ITEM_MULT)
|
|
if baseline.item_fits_role(item, role):
|
|
mult *= baseline.ROLE_FIT_BONUS
|
|
value *= mult
|
|
total += value
|
|
|
|
for trait, ordinal in active_trait_tiers(board_units, static_traits, static_units).items():
|
|
default = baseline.DEFAULT_TRAIT_TIER_MULT[
|
|
min(ordinal, len(baseline.DEFAULT_TRAIT_TIER_MULT) - 1)
|
|
]
|
|
total *= trait_mults.get(f"{trait}@{ordinal}", default)
|
|
|
|
for augment in augments:
|
|
total *= augment_mults.get(augment, 1.0)
|
|
|
|
names = sorted({u["api_name"] for u in board_units})
|
|
lift_sum = sum(
|
|
pair_lifts.get(f"{a}|{b}", 0.0)
|
|
for i, a in enumerate(names)
|
|
for b in names[i + 1 :]
|
|
)
|
|
total *= 1 + min(max(lift_sum * 0.01, -0.10), 0.10)
|
|
|
|
return total
|