This commit is contained in:
2026-03-19 22:53:33 +01:00
parent fa05447895
commit d0faa5830c

View File

@@ -3,7 +3,7 @@ import random
import logging import logging
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
from itertools import combinations from itertools import combinations, permutations
from card import Card from card import Card
from game import action_play_card, action_sacrifice, action_end_turn, BOARD_SIZE, STARTING_LIFE from game import action_play_card, action_sacrifice, action_end_turn, BOARD_SIZE, STARTING_LIFE
@@ -40,14 +40,6 @@ def get_power_curve_value(card) -> float:
def choose_cards(cards: list[Card], difficulty: int, personality: AIPersonality) -> list[Card]: def choose_cards(cards: list[Card], difficulty: int, personality: AIPersonality) -> list[Card]:
BUDGET = 50 BUDGET = 50
logger.info(f"Personality: {personality.value}")
logger.info(f"Difficulty: {difficulty}")
card_strings = [
f"{c.name} {c.cost}"
for c in sorted(cards, key=lambda x: x.cost)[::-1][:20]
]
logger.info("Cards:\n"+("\n".join(card_strings)))
# God cards (cost 7-11) are gated by difficulty. Below difficulty 7 they are excluded. # God cards (cost 7-11) are gated by difficulty. Below difficulty 7 they are excluded.
# Each level from 7 upward unlocks a higher cost tier; at difficulty 10 all are allowed. # Each level from 7 upward unlocks a higher cost tier; at difficulty 10 all are allowed.
if difficulty >= 6: if difficulty >= 6:
@@ -139,13 +131,6 @@ def choose_cards(cards: list[Card], difficulty: int, personality: AIPersonality)
selected.append(card) selected.append(card)
total_cost += card.cost total_cost += card.cost
card_strings = [
f"{c.name} {c.cost}"
for c in sorted(selected, key=lambda x: x.cost)
]
logger.info("Selected:\n"+("\n".join(card_strings)))
return selected return selected
@@ -182,13 +167,6 @@ def _plans_for_sacrifice(player, opponent, sacrifice_slots):
empty_slots = [i for i, c in enumerate(board) if c is None] empty_slots = [i for i, c in enumerate(board) if c is None]
en_board = opponent.board en_board = opponent.board
# For scoring: open enemy slots first so the simulation reflects
# direct-damage potential accurately.
scoring_slots = (
[s for s in empty_slots if en_board[s] is None] +
[s for s in empty_slots if en_board[s] is not None]
)
return [ return [
MovePlan( MovePlan(
sacrifice_slots=list(sacrifice_slots), sacrifice_slots=list(sacrifice_slots),
@@ -196,6 +174,7 @@ def _plans_for_sacrifice(player, opponent, sacrifice_slots):
label=f"sac{len(sacrifice_slots)}_play{len(cards)}", label=f"sac{len(sacrifice_slots)}_play{len(cards)}",
) )
for cards in _affordable_subsets(hand, energy) for cards in _affordable_subsets(hand, energy)
for scoring_slots in permutations(empty_slots, len(cards))
] ]
@@ -501,10 +480,10 @@ async def run_ai_turn(game_id: str):
for p in plans] for p in plans]
best_plan = max(scored, key=lambda x: x[0])[1] best_plan = max(scored, key=lambda x: x[0])[1]
logger.info( # logger.info(
f"AI turn: d={difficulty} p={personality.value} plan={best_plan.label} plans={len(plans)} " + # f"AI turn: d={difficulty} p={personality.value} plan={best_plan.label} plans={len(plans)} " +
f"sac={best_plan.sacrifice_slots} plays={[c.name for c, _ in best_plan.plays]}" # f"sac={best_plan.sacrifice_slots} plays={[c.name for c, _ in best_plan.plays]}"
) # )
# --- Execute sacrifices --- # --- Execute sacrifices ---
for slot in best_plan.sacrifice_slots: for slot in best_plan.sacrifice_slots: