kards-env/kards_battle/cards/card_manager.py

252 lines
7.5 KiB
Python
Raw Normal View History

2025-09-05 17:05:43 +08:00
"""
卡牌管理器 - 管理手牌抽牌堆弃牌堆
"""
from typing import List, Optional, Set
import random
from collections import deque
from .card import BaseCard
from .deck import Deck
class CardManager:
"""卡牌管理器 - 管理单个玩家的所有卡牌状态"""
def __init__(self, deck: Deck):
self.deck = deck
# 抽牌堆 - 使用deque提高性能
self.draw_pile: deque = deque(deck.get_deck_cards())
# 手牌
self.hand: List[BaseCard] = []
# 弃牌堆
self.discard_pile: List[BaseCard] = []
# 疲劳系统
self.fatigue_damage = 1 # 当前疲劳伤害
self.total_fatigue_taken = 0 # 总疲劳伤害
# 战略调度标记
self.strategic_deployment_completed = False
# 手牌大小限制(如果有的话)
self.max_hand_size = 10 # 默认最大手牌数
# 洗牌抽牌堆
self.shuffle_draw_pile()
def shuffle_draw_pile(self):
"""洗牌抽牌堆"""
draw_list = list(self.draw_pile)
random.shuffle(draw_list)
self.draw_pile = deque(draw_list)
def draw_card(self, hq_defense_callback: callable = None) -> Optional[BaseCard]:
"""
抽一张牌
如果抽牌堆为空对HQ造成疲劳伤害
Args:
hq_defense_callback: HQ受伤回调函数接收伤害值作为参数
Returns:
抽到的卡牌如果抽牌堆为空且造成疲劳伤害则返回None
"""
if self.draw_pile:
# 正常抽牌
card = self.draw_pile.popleft()
self.hand.append(card)
return card
else:
# 抽牌堆为空,造成疲劳伤害
if hq_defense_callback:
hq_defense_callback(self.fatigue_damage)
self.total_fatigue_taken += self.fatigue_damage
self.fatigue_damage += 1 # 疲劳伤害递增
return None
def draw_multiple_cards(self, count: int, hq_defense_callback: callable = None) -> List[BaseCard]:
"""
抽多张牌
Args:
count: 要抽的牌数
hq_defense_callback: HQ受伤回调函数
Returns:
成功抽到的卡牌列表
"""
drawn_cards = []
for _ in range(count):
card = self.draw_card(hq_defense_callback)
if card:
drawn_cards.append(card)
return drawn_cards
def initial_draw(self, count: int) -> List[BaseCard]:
"""
初始摸牌不会触发疲劳伤害
Args:
count: 要抽的牌数
Returns:
抽到的卡牌列表
"""
drawn_cards = []
for _ in range(min(count, len(self.draw_pile))):
if self.draw_pile:
card = self.draw_pile.popleft()
self.hand.append(card)
drawn_cards.append(card)
return drawn_cards
def play_card_from_hand(self, card: BaseCard) -> bool:
"""
从手牌打出一张卡
Args:
card: 要打出的卡牌
Returns:
是否成功从手牌移除
"""
if card in self.hand:
self.hand.remove(card)
return True
return False
def discard_card(self, card: BaseCard):
"""将卡牌放入弃牌堆"""
self.discard_pile.append(card)
def discard_from_hand(self, card: BaseCard) -> bool:
"""
从手牌弃置一张卡
Args:
card: 要弃置的卡牌
Returns:
是否成功弃置
"""
if card in self.hand:
self.hand.remove(card)
self.discard_card(card)
return True
return False
def strategic_deployment(self, cards_to_mulligan: List[BaseCard]) -> List[BaseCard]:
"""
战略调度 - 重新抽取不想要的卡牌
Args:
cards_to_mulligan: 要重抽的卡牌列表
Returns:
新抽到的卡牌列表
"""
if self.strategic_deployment_completed:
raise ValueError("战略调度已经完成,不能重复进行")
# 验证所有卡牌都在手牌中
for card in cards_to_mulligan:
if card not in self.hand:
raise ValueError(f"卡牌 {card.name} 不在手牌中")
# 移除要重抽的卡牌
for card in cards_to_mulligan:
self.hand.remove(card)
# 将这些卡牌放回抽牌堆
for card in cards_to_mulligan:
self.draw_pile.append(card)
# 重新洗牌
self.shuffle_draw_pile()
# 抽取相同数量的新卡
new_cards = []
for _ in range(len(cards_to_mulligan)):
if self.draw_pile:
card = self.draw_pile.popleft()
self.hand.append(card)
new_cards.append(card)
self.strategic_deployment_completed = True
return new_cards
def can_draw_safely(self) -> bool:
"""检查是否可以安全抽牌(不会触发疲劳)"""
return len(self.draw_pile) > 0
def cards_remaining_in_deck(self) -> int:
"""返回抽牌堆剩余卡牌数量"""
return len(self.draw_pile)
def hand_size(self) -> int:
"""返回当前手牌数量"""
return len(self.hand)
def is_hand_full(self) -> bool:
"""检查手牌是否已满"""
return len(self.hand) >= self.max_hand_size
def get_hand_copy(self) -> List[BaseCard]:
"""获取手牌的副本"""
return self.hand.copy()
def get_card_in_hand_by_name(self, name: str) -> Optional[BaseCard]:
"""根据名称在手牌中查找卡牌"""
for card in self.hand:
if card.name == name:
return card
return None
def get_playable_cards(self, current_kredits: int) -> List[BaseCard]:
"""
获取当前可以打出的卡牌基于费用
Args:
current_kredits: 当前可用的kredits
Returns:
可以打出的卡牌列表
"""
playable = []
for card in self.hand:
if card.stats.cost <= current_kredits:
playable.append(card)
return playable
def reshuffle_discard_into_deck(self):
"""
将弃牌堆重新洗入抽牌堆
这个功能可能在某些特殊卡牌效果中使用
"""
if self.discard_pile:
# 将弃牌堆的卡牌加入抽牌堆
for card in self.discard_pile:
self.draw_pile.append(card)
# 清空弃牌堆
self.discard_pile.clear()
# 重新洗牌
self.shuffle_draw_pile()
def get_statistics(self) -> dict:
"""获取卡牌管理器统计信息"""
return {
'hand_size': len(self.hand),
'cards_in_deck': len(self.draw_pile),
'cards_in_discard': len(self.discard_pile),
'fatigue_damage': self.fatigue_damage,
'total_fatigue_taken': self.total_fatigue_taken,
'strategic_deployment_used': self.strategic_deployment_completed,
'max_hand_size': self.max_hand_size
}