🐐
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user