This commit is contained in:
Nikolaj
2026-03-26 08:16:54 +01:00
parent ef4496aa5d
commit ec7dea2d72
5 changed files with 18 additions and 46 deletions

View File

@@ -13,19 +13,17 @@ logger = logging.getLogger("app")
AI_USER_ID = "ai"
class AIPersonality(Enum):
AGGRESSIVE = "aggressive" # Prefers high attack cards, plays aggressively
DEFENSIVE = "defensive" # Prefers high defense cards, plays conservatively
BALANCED = "balanced" # Mix of offense and defense
GREEDY = "greedy" # Prioritizes high cost cards, willing to sacrifice
SWARM = "swarm" # Prefers low cost cards, fills board quickly
CONTROL = "control" # Focuses on board control and efficiency
ARBITRARY = "arbitrary" # Just does whatever
JEBRASKA = "jebraska" # Trained neural network plan scorer
AGGRESSIVE = "aggressive"
DEFENSIVE = "defensive"
BALANCED = "balanced"
GREEDY = "greedy" # prioritizes high cost cards, willing to sacrifice
SWARM = "swarm"
CONTROL = "control"
ARBITRARY = "arbitrary"
JEBRASKA = "jebraska" # trained neural network plan scorer
def get_random_personality() -> AIPersonality:
"""Returns a random AI personality."""
# return random.choice(list(AIPersonality))
return AIPersonality.JEBRASKA
return random.choice(list(AIPersonality))
def calculate_exact_cost(attack: int, defense: int) -> float:
"""Calculate the exact cost before rounding (matches card.py formula)."""
@@ -130,8 +128,6 @@ def choose_cards(cards: list[Card], difficulty: int, personality: AIPersonality)
return selected
# ==================== Turn planning ====================
@dataclass
class MovePlan:
sacrifice_slots: list[int]
@@ -175,7 +171,6 @@ def _plans_for_sacrifice(player, opponent, sacrifice_slots):
def generate_plans(player, opponent) -> list[MovePlan]:
"""Generate diverse candidate move plans covering a range of strategies."""
plans = []
# Sacrifice n board cards
@@ -189,8 +184,6 @@ def generate_plans(player, opponent) -> list[MovePlan]:
return plans
# ==================== Turn execution ====================
def score_plans_batch(
plans: list[MovePlan],
player: PlayerState,
@@ -205,7 +198,7 @@ def score_plans_batch(
for c in player.hand
}
# Build board-state arrays with one Python loop (unavoidable)
# Build board-state arrays
board_atk = np.zeros((n, BOARD_SIZE), dtype=np.float32)
board_occ = np.zeros((n, BOARD_SIZE), dtype=np.bool_)
n_sac = np.zeros(n, dtype=np.float32)
@@ -390,7 +383,6 @@ async def run_ai_turn(game_id: str):
except Exception:
pass
# --- Generate and score candidate plans ---
best_plan = choose_plan(player, opponent, personality, difficulty)
logger.info(
@@ -398,7 +390,6 @@ async def run_ai_turn(game_id: str):
f"sac={best_plan.sacrifice_slots} plays={[c.name for c, _ in best_plan.plays]}"
)
# --- Execute sacrifices ---
for slot in best_plan.sacrifice_slots:
card_slot = player.board[slot]
if card_slot is None:
@@ -409,7 +400,6 @@ async def run_ai_turn(game_id: str):
await send_state(state)
await asyncio.sleep(0.35)
# --- Execute plays ---
# Shuffle play order so the AI doesn't always fill slots left-to-right
plays = list(best_plan.plays)
random.shuffle(plays)