#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
KARDS - 二战卡牌对战（完整单文件版）
包含：6阵营×15专属卡 + 通用指令 + 10种关键词 + 阵营加成 + 锁定机制
     + 反击/部署冷却/疲劳/手牌上限 + 策略AI + 战报日志
纯 Tkinter，无需额外依赖
"""

import tkinter as tk
from tkinter import ttk, messagebox
import random
import math
import copy

# ============================================================
# 常量
# ============================================================
MAX_HQ = 20
HAND_LIMIT = 10
DECK_SIZE = 40
ALLY_LIMIT = 12
ZONE_CAP = 5
MAX_CP = 12
FATIGUE_BASE = 1
CARD_W, CARD_H = 100, 140

FACTIONS = {
    "苏联": {"color": "#CC0000", "bonus": "钢铁洪流：坦克单位部署费用-1"},
    "德国": {"color": "#222222", "bonus": "闪电战：每回合首次移动不消耗移动力"},
    "美国": {"color": "#3A5FCD", "bonus": "后勤优势：第3回合起每回合额外抽1张"},
    "英国": {"color": "#8B8B00", "bonus": "坚不可摧：支援阵线单位防御+1"},
    "日本": {"color": "#FF6600", "bonus": "玉碎：单位阵亡时对敌方随机目标造成1点伤害"},
    "法国": {"color": "#0055AA", "bonus": "顽强：总部防御+3"},
}

KEYWORDS = {
    "blitz": "闪击：部署当回合即可攻击",
    "armor": "装甲：受击伤害-1(最低1)",
    "pierce": "穿甲：攻击时无视1点防御",
    "anti_air": "防空：攻击空军时伤害+2",
    "airborne": "飞行：地面单位无法直接攻击",
    "artillery_range": "远程：攻击不受反击",
    "guard": "守卫：敌方须优先攻击此单位",
    "inspire": "激励：相邻友军攻击+1",
    "ambush": "伏击：首次被攻击时伤害-2",
    "heal_on_kill": "杀回：摧毁目标时恢复2防御",
}

# ============================================================
# 卡牌数据
# ============================================================
def make_unit(name, cost, atk, defense, mov, unit_type, faction, keywords=None, icon="🪖"):
    return {"type":"unit","name":name,"cost":cost,"atk":atk,"def_":defense,"max_def":defense,
            "mov":mov,"mov_remaining":mov,"unit":unit_type,"faction":faction,
            "keywords":keywords or [],"icon":icon,
            "summoned_this_turn":False,"moved_this_turn":False,"attacked_this_turn":False}

def make_order(name, cost, desc, kind, faction, **kwargs):
    return {"type":"order","name":name,"cost":cost,"desc":desc,
            "data":{"kind":kind,**kwargs},"faction":faction,"icon":"📜"}

# --- 苏联 ---
SOVIET = [
    make_unit("近卫步兵",2,3,3,1,"infantry","苏联",[],"🪖"),
    make_unit("T-34坦克",4,6,5,1,"tank","苏联",["blitz"],"🪖"),
    make_unit("喀秋莎火箭炮",3,4,2,0,"artillery","苏联",["artillery_range"],"🪖"),
    make_unit("IL-2攻击机",4,5,3,2,"fighter","苏联",["anti_air"],"✈️"),
    make_unit("KV-2重型坦克",6,7,8,1,"tank","苏联",["armor"],"🪖"),
    make_unit("政委",1,1,1,1,"infantry","苏联",["inspire"],"🪖"),
    make_unit("红军冲锋",3,4,3,1,"infantry","苏联",["blitz"],"🪖"),
    make_unit("Pe-8轰炸机",6,7,4,2,"bomber","苏联",["pierce"],"✈️"),
    make_unit("反坦克步枪",2,3,1,0,"infantry","苏联",["pierce"],"🪖"),
    make_unit("西伯利亚师",5,5,6,1,"infantry","苏联",["armor"],"🪖"),
    make_unit("雅克战斗机",3,4,2,2,"fighter","苏联",["anti_air"],"✈️"),
    make_unit("斯大林之锤",7,8,5,0,"artillery","苏联",["artillery_range","pierce"],"🪖"),
    make_unit("工兵",2,2,3,1,"infantry","苏联",["guard"],"🪖"),
    make_unit("侦察骑兵",2,2,2,2,"infantry","苏联",["blitz"],"🪖"),
    make_unit("IS-2重型坦克",7,8,7,1,"tank","苏联",["armor","pierce"],"🪖"),
    make_order("乌拉冲锋",2,"我方1单位\n本回合+2攻击","buff","苏联",atk_bonus=2),
    make_order("焦土战术",3,"对敌方前线\n造成3点伤害","damage_line","苏联",val=3,line="e_front"),
    make_order("冬将军",4,"所有敌方单位\n防御-2","damage_all","苏联",val=2),
]
# --- 德国 ---
GERMAN = [
    make_unit("装甲掷弹兵",3,4,4,1,"infantry","德国",[],"🪖"),
    make_unit("虎式坦克",5,7,7,1,"tank","德国",["armor"],"🪖"),
    make_unit("斯图卡俯冲轰炸机",4,5,2,2,"fighter","德国",["anti_air","pierce"],"✈️"),
    make_unit("88毫米炮",3,4,2,0,"artillery","德国",["anti_air","artillery_range"],"🪖"),
    make_unit("豹式坦克",5,6,6,1,"tank","德国",["blitz"],"🪖"),
    make_unit("闪电突击",2,3,2,2,"tank","德国",["blitz"],"🪖"),
    make_unit("伞兵",2,3,2,1,"infantry","德国",["airborne"],"🪖"),
    make_unit("俾斯麦号",7,8,8,0,"artillery","德国",["artillery_range","armor"],"🪖"),
    make_unit("U艇",3,4,3,1,"fighter","德国",["ambush"],"✈️"),
    make_unit("党卫军",3,4,4,1,"infantry","德国",["inspire"],"🪖"),
    make_unit("FW-190战斗机",3,5,2,2,"fighter","德国",["anti_air"],"✈️"),
    make_unit("猎豹坦克歼击车",5,7,5,1,"tank","德国",["pierce","ambush"],"🪖"),
    make_unit("喷烟者",3,3,4,0,"artillery","德国",["artillery_range"],"🪖"),
    make_unit("突击工兵",2,3,3,1,"infantry","德国",["guard"],"🪖"),
    make_unit("Me-262喷气式",6,7,3,3,"fighter","德国",["blitz","anti_air"],"✈️"),
    make_order("闪电战指令",2,"我方1坦克\n本回合可移动+攻击","buff","德国",mov_bonus=1),
    make_order("狼群战术",3,"对敌方总部\n造成4点伤害","damage_hq","德国",val=4),
    make_order("战术撤退",1,"将我方1单位\n移回支援阵线","move_back","德国"),
]
# --- 美国 ---
USA = [
    make_unit("谢尔曼坦克",4,5,5,1,"tank","美国",["blitz"],"🪖"),
    make_unit("步兵班",2,2,4,1,"infantry","美国",["guard"],"🪖"),
    make_unit("P-51野马",4,5,3,2,"fighter","美国",["anti_air"],"✈️"),
    make_unit("B-17空中堡垒",6,6,5,2,"bomber","美国",["artillery_range"],"✈️"),
    make_unit("M10坦克歼击车",4,6,3,1,"tank","美国",["pierce"],"🪖"),
    make_unit("海军陆战队",3,4,4,1,"infantry","美国",["inspire"],"🪖"),
    make_unit("航空母舰",7,5,8,0,"artillery","美国",["artillery_range","armor"],"🪖"),
    make_unit("伞兵空降",2,3,2,1,"infantry","美国",["airborne","blitz"],"🪖"),
    make_unit("M4A3E8",5,6,6,1,"tank","美国",["armor"],"🪖"),
    make_unit("F4U海盗",3,5,2,2,"fighter","美国",["anti_air"],"✈️"),
    make_unit("M7牧师",3,4,2,0,"artillery","美国",["artillery_range"],"🪖"),
    make_unit("游骑兵",2,3,3,2,"infantry","美国",["blitz"],"🪖"),
    make_unit("M26潘兴",6,7,7,1,"tank","美国",["armor","pierce"],"🪖"),
    make_unit("B-29超级堡垒",8,8,6,2,"bomber","美国",["pierce","artillery_range"],"✈️"),
    make_unit("补给兵",1,1,2,1,"infantry","美国",["heal_on_kill"],"🪖"),
    make_order("D-Day空降",3,"召唤2个\n2/2伞兵","summon_multi","美国",count=2,unit="infantry",a=2,d=2),
    make_order("战略轰炸",4,"对敌方所有单位\n造成2点伤害","damage_all","美国",val=2),
    make_order("后勤补给",1,"抽2张牌","draw","美国",val=2),
]
# --- 英国 ---
BRITISH = [
    make_unit("步兵排",2,2,4,1,"infantry","英国",["guard"],"🪖"),
    make_unit("丘吉尔坦克",5,5,8,1,"tank","英国",["armor"],"🪖"),
    make_unit("喷火战斗机",3,4,3,2,"fighter","英国",["anti_air"],"✈️"),
    make_unit("重炮阵地",3,3,3,0,"artillery","英国",["artillery_range"],"🪖"),
    make_unit("皇家海军",4,5,5,1,"tank","英国",["armor"],"🪖"),
    make_unit("突击队",2,3,2,2,"infantry","英国",["blitz"],"🪖"),
    make_unit("飓风战斗机",3,4,2,2,"fighter","英国",["anti_air"],"✈️"),
    make_unit("马蒂尔达",4,4,7,1,"tank","英国",["armor"],"🪖"),
    make_unit("萤火虫坦克",5,7,4,1,"tank","英国",["pierce"],"🪖"),
    make_unit("苏格兰高地师",3,3,5,1,"infantry","英国",["inspire"],"🪖"),
    make_unit("兰开斯特轰炸机",6,6,4,2,"bomber","英国",["artillery_range"],"✈️"),
    make_unit("反坦克炮",2,4,1,0,"artillery","英国",["pierce","ambush"],"🪖"),
    make_unit("沙漠鼠",3,4,5,1,"infantry","英国",["guard"],"🪖"),
    make_unit("哥特式轰炸",5,5,3,2,"bomber","英国",["pierce"],"✈️"),
    make_unit("蒙哥马利",2,2,3,1,"infantry","英国",["inspire","guard"],"🪖"),
    make_order("不列颠空战",3,"对所有敌方空军\n造成3点伤害","damage_air","英国",val=3),
    make_order("敦刻尔克",2,"将我方1单位\n从弃牌堆回收","recall","英国"),
    make_order("雷达预警",1,"查看敌方手牌\n并抽1张","scout","英国",val=1),
]
# --- 日本 ---
JAPAN = [
    make_unit("零式战斗机",3,5,2,2,"fighter","日本",["blitz","anti_air"],"✈️"),
    make_unit("武士步兵",2,4,2,1,"infantry","日本",["blitz"],"🪖"),
    make_unit("九七式中战车",3,4,4,1,"tank","日本",[],"🪖"),
    make_unit("神风特攻",1,6,1,2,"fighter","日本",["ambush","heal_on_kill"],"✈️"),
    make_unit("海军陆战队",2,3,3,1,"infantry","日本",["guard"],"🪖"),
    make_unit("一式战斗机",3,4,2,2,"fighter","日本",["anti_air"],"✈️"),
    make_unit("樱花特攻机",2,7,1,2,"fighter","日本",["pierce","ambush"],"✈️"),
    make_unit("九二式步兵炮",2,3,2,0,"artillery","日本",["artillery_range"],"🪖"),
    make_unit("战列舰大和",8,9,9,0,"artillery","日本",["artillery_range","armor"],"🪖"),
    make_unit("关东军精锐",3,4,4,1,"infantry","日本",["inspire"],"🪖"),
    make_unit("一式坦克",4,5,5,1,"tank","日本",["armor"],"🪖"),
    make_unit("九九式轰炸机",5,6,3,2,"bomber","日本",["pierce"],"✈️"),
    make_unit("特攻艇",2,5,1,1,"tank","日本",["ambush"],"🪖"),
    make_unit("忍者",1,3,1,3,"infantry","日本",["blitz","ambush"],"🪖"),
    make_unit("菊水特攻",3,8,2,1,"tank","日本",["pierce","heal_on_kill"],"🪖"),
    make_order("玉碎冲锋",1,"我方1单位\n攻击力翻倍","buff","日本",atk_bonus=99,temp=True),
    make_order("神风指令",2,"对敌方前线\n造成5点伤害","damage_line","日本",val=5,line="e_front"),
    make_order("武士道",2,"我方1单位\n+2/+2","buff","日本",atk_bonus=2,def_bonus=2),
]
# --- 法国 ---
FRANCE = [
    make_unit("外籍军团",2,3,4,1,"infantry","法国",["guard"],"🪖"),
    make_unit("索玛S35坦克",4,5,6,1,"tank","法国",["armor"],"🪖"),
    make_unit("马奇诺防线",3,2,6,0,"artillery","法国",["guard","armor"],"🪖"),
    make_unit("D.520战斗机",3,4,3,2,"fighter","法国",["anti_air"],"✈️"),
    make_unit("自由法国军",2,3,3,1,"infantry","法国",["inspire"],"🪖"),
    make_unit("夏尔B1坦克",5,6,7,1,"tank","法国",["armor","pierce"],"🪖"),
    make_unit("雷诺R35",3,3,5,1,"tank","法国",["guard"],"🪖"),
    make_unit("法军炮兵",2,3,2,0,"artillery","法国",["artillery_range"],"🪖"),
    make_unit("抵抗军战士",1,2,2,2,"infantry","法国",["ambush"],"🪖"),
    make_unit("黎塞留号",6,7,7,0,"artillery","法国",["artillery_range","armor"],"🪖"),
    make_unit("布雷盖轰炸机",4,5,3,2,"bomber","法国",["pierce"],"✈️"),
    make_unit("殖民地步兵",2,3,4,1,"infantry","法国",["inspire"],"🪖"),
    make_unit("洛林坦克",4,5,5,1,"tank","法国",[],"🪖"),
    make_unit("法军骑兵",2,3,2,2,"infantry","法国",["blitz"],"🪖"),
    make_unit("戴高乐",2,2,3,1,"infantry","法国",["inspire","guard"],"🪖"),
    make_order("马奇诺坚守",2,"我方所有单位\n防御+2","buff_all","法国",def_bonus=2),
    make_order("自由号召",3,"召唤1个\n3/4外籍军团","summon","法国",unit="infantry",a=3,d=4),
    make_order("游击战",1,"对敌方1目标\n造成2点伤害","damage_any","法国",val=2),
]
# --- 通用指令 ---
GENERAL = [
    make_order("炮火覆盖",2,"对敌方前线1目标\n造成2点伤害","damage_line","通用",val=2,line="e_front"),
    make_order("战术打击",3,"对敌方任意目标\n造成4点伤害","damage_any","通用",val=4),
    make_order("纵深打击",4,"对敌方总部\n造成3点伤害","damage_hq","通用",val=3),
    make_order("增援动员",2,"召唤1个1/1步兵\n到我方前线","summon","通用",unit="infantry",a=1,d=1),
    make_order("空中支援",3,"召唤1个2/2战斗机","summon","通用",unit="fighter",a=2,d=2),
    make_order("紧急维修",1,"为我方1目标\n恢复2防御","heal","通用",val=2),
    make_order("侦察",1,"抽1张牌","draw","通用",val=1),
    make_order("集中火力",2,"我方1单位\n本回合+3攻击","buff","通用",atk_bonus=3),
    make_order("加固阵地",2,"我方1单位\n防御+3","buff","通用",def_bonus=3),
    make_order("烟雾弹",1,"敌方1单位\n本回合无法攻击","disable","通用"),
]

ALL_FACTIONS_CARDS = {"苏联":SOVIET,"德国":GERMAN,"美国":USA,"英国":BRITISH,"日本":JAPAN,"法国":FRANCE}

# ============================================================
# 游戏状态
# ============================================================
class GameState:
    def __init__(self):
        self.reset()

    def reset(self):
        self.turn=1
        self.phase="play"
        self.game_over=False
        self.winner=None
        self.player=None
        self.ally=None
        self.enemy_faction=None
        self.go_first=True
        self.player_hq=MAX_HQ
        self.enemy_hq=MAX_HQ
        self.player_cp=1
        self.enemy_cp=1
        self.cp_cap=1
        self.fatigue=1
        self.player_deck=[]
        self.enemy_deck=[]
        self.player_hand=[]
        self.enemy_hand=[]
        self.board={"p_front":[],"p_support":[],"e_front":[],"e_support":[]}
        self.selected=None
        self.pending_action=None
        self.log=[]
        self.german_move_used=False

    def log_msg(self,msg):
        self.log.append(msg)
        if len(self.log)>60:
            self.log.pop(0)

    def front_occupied(self,side):
        return len(self.board[f"{side}_front"])>0

    def can_target_hq(self,attacker_side):
        enemy="e" if attacker_side=="p" else "p"
        return not self.front_occupied(enemy)

    def get_valid_targets(self,attacker,attacker_side,attacker_line):
        enemy="e" if attacker_side=="p" else "p"
        targets=[]
        for i,u in enumerate(self.board[f"{enemy}_front"]):
            targets.append(("unit",f"{enemy}_front",i,u))
        if not self.front_occupied(enemy):
            for i,u in enumerate(self.board[f"{enemy}_support"]):
                targets.append(("unit",f"{enemy}_support",i,u))
            targets.append(("hq",enemy,-1,None))
        return targets

    def build_deck(self,faction,ally):
        pool_main=list(ALL_FACTIONS_CARDS[faction])
        pool_ally=list(ALL_FACTIONS_CARDS[ally]) if ally else []
        pool_gen=list(GENERAL)
        deck=[]
        ally_count=0
        for _ in range(DECK_SIZE):
            r=random.random()
            if ally and r<0.30 and ally_count<ALLY_LIMIT:
                c=copy.deepcopy(random.choice(pool_ally))
                ally_count+=1
            elif r<0.82:
                c=copy.deepcopy(random.choice(pool_main))
            else:
                c=copy.deepcopy(random.choice(pool_gen))
            deck.append(c)
        random.shuffle(deck)
        return deck

    def start_match(self,faction,ally,go_first):
        self.reset()
        self.player=faction
        self.ally=ally
        self.go_first=go_first
        self.player_deck=self.build_deck(faction,ally)
        self.enemy_faction=random.choice([f for f in FACTIONS if f!=faction])
        self.enemy_deck=self.build_deck(self.enemy_faction,None)
        # 法国加成
        if faction=="法国":
            self.player_hq=MAX_HQ+3
        if self.enemy_faction=="法国":
            self.enemy_hq=MAX_HQ+3
        # 起手
        if go_first:
            self.player_hand=self.player_deck[:4]
            self.player_deck=self.player_deck[4:]
            self.enemy_hand=self.enemy_deck[:5]
            self.enemy_deck=self.enemy_deck[5:]
        else:
            self.player_hand=self.player_deck[:5]
            self.player_deck=self.player_deck[5:]
            self.enemy_hand=self.enemy_deck[:4]
            self.enemy_deck=self.enemy_deck[4:]
        self.log_msg(f"🎖️ 你：{faction}"+(f" + 盟国{ally}" if ally else ""))
        self.log_msg(f"⚔ 敌方：{self.enemy_faction}")
        self.log_msg("🔥 战斗开始！"+( " 你先手。" if go_first else " 敌方先手。"))

    def deploy(self,hand_idx,line,side="p"):
        if side=="p":
            if self.player_cp<self.player_hand[hand_idx]["cost"]:
                return False,"指挥点不足"
            if len(self.board[f"p_{line}"])>=ZONE_CAP:
                return False,"阵线已满"
            c=copy.deepcopy(self.player_hand.pop(hand_idx))
            # 苏联加成
            if self.player=="苏联" and c.get("unit")=="tank":
                self.player_cp-=max(0,c["cost"]-1)
            else:
                self.player_cp-=c["cost"]
            c["summoned_this_turn"]=True
            c["mov_remaining"]=c.get("mov",1)
            self.board[f"p_{line}"].append(c)
            self.log_msg(f"⚔ 部署 {c['name']} 到{'前线' if line=='front' else '支援'}")
            return True,"部署成功"
        else:
            if self.enemy_cp<self.enemy_hand[hand_idx]["cost"]:
                return False,"指挥点不足"
            if len(self.board[f"e_{line}"])>=ZONE_CAP:
                return False,"阵线已满"
            c=copy.deepcopy(self.enemy_hand.pop(hand_idx))
            self.enemy_cp-=c["cost"]
            c["summoned_this_turn"]=True
            c["mov_remaining"]=c.get("mov",1)
            self.board[f"e_{line}"].append(c)
            self.log_msg(f"🤖 敌方部署 {c['name']}")
            return True,"部署成功"

    def move(self,from_line,to_line,idx,side="p"):
        if from_line==to_line:
            return False,"已在目标阵线"
        if len(self.board[f"{side}_{to_line}"])>=ZONE_CAP:
            return False,"目标阵线已满"
        c=self.board[f"{side}_{from_line}"].pop(idx)
        c["moved_this_turn"]=True
        if side=="p" and self.player=="德国" and not self.german_move_used:
            self.german_move_used=True
        else:
            c["mov_remaining"]=max(0,c.get("mov_remaining",c.get("mov",1))-1)
        self.board[f"{side}_{to_line}"].append(c)
        self.log_msg(f"➡ {c['name']} 移至{'前线' if to_line=='front' else '支援'}")
        return True,"移动成功"

    def attack_unit(self,att_side,att_line,aidx,tgt_side,tgt_line,tidx):
        a=self.board[f"{att_side}_{att_line}"][aidx]
        t=self.board[f"{tgt_side}_{tgt_line}"][tidx]
        a["attacked_this_turn"]=True
        dmg_a=a["atk"]
        dmg_t=t.get("atk",0)
        # 关键词
        if "pierce" in a.get("keywords",[]): dmg_a+=1
        if "anti_air" in a.get("keywords",[]) and t.get("unit") in ("fighter","bomber"): dmg_a+=2
        if "artillery_range" in a.get("keywords",[]): dmg_t=0
        if "armor" in t.get("keywords",[]): dmg_t=max(1,dmg_t-1)
        if "ambush" in t.get("keywords",[]):
            dmg_t=max(0,dmg_t-2)
            t["keywords"].remove("ambush")
        if att_side=="p" and self.player=="英国" and att_line=="support":
            pass
        if tgt_side=="p" and self.player=="英国" and tgt_line=="support":
            dmg_a=max(0,dmg_a-1)
        t["def_"]-=dmg_a
        a["def_"]-=dmg_t
        self.log_msg(f"⚔ {a['name']}→{t['name']}：伤{dmg_a}"+(f" 受{dmg_t}" if dmg_t>0 else ""))
        if t["def_"]<=0 and "heal_on_kill" in a.get("keywords",[]):
            a["def_"]=min(a.get("max_def",a["def_"]),a["def_"]+2)
            self.log_msg(f"💚 {a['name']} 杀回+2防御")
        # 日本玉碎
        if t["def_"]<=0 and t.get("faction")=="日本":
            self._japanese_last_stand()
        msgs=[]
        if t["def_"]<=0:
            self.board[f"{tgt_side}_{tgt_line}"].pop(tidx)
            self.log_msg(f"💀 {t['name']} 被摧毁")
            msgs.append("tgt_died")
        if a["def_"]<=0:
            self.board[f"{att_side}_{att_line}"].pop(aidx)
            self.log_msg(f"💀 {a['name']} 在攻击中阵亡")
            msgs.append("att_died")
        return True,"攻击完成"

    def attack_hq_act(self,att_side,att_line,aidx,tgt_side):
        a=self.board[f"{att_side}_{att_line}"][aidx]
        if not self.can_target_hq(att_side):
            return False,"敌方前线未清空"
        a["attacked_this_turn"]=True
        dmg=a["atk"]
        if "pierce" in a.get("keywords",[]): dmg+=1
        if tgt_side=="e":
            self.enemy_hq-=dmg
            self.log_msg(f"💥 {a['name']} 直击敌方总部 -{dmg}!")
            if self.enemy_hq<=0: self.game_over=True; self.winner="player"
        else:
            self.player_hq-=dmg
            self.log_msg(f"💥 {a['name']} 直击我方总部 -{dmg}!")
            if self.player_hq<=0: self.game_over=True; self.winner="enemy"
        return True,"攻击总部"

    def use_order(self,hand_idx,side="p",target=None):
        if side=="p":
            c=self.player_hand[hand_idx]
            if self.player_cp<c["cost"]: return False,"指挥点不足"
            self.player_cp-=c["cost"]
            self.player_hand.pop(hand_idx)
        else:
            c=self.enemy_hand[hand_idx]
            if self.enemy_cp<c["cost"]: return False,"指挥点不足"
            self.enemy_cp-=c["cost"]
            self.enemy_hand.pop(hand_idx)
        od=c["data"]
        r=self._apply_order(od,side,target)
        self.log_msg(f"📜 {c['name']}：{r}")
        return True,r

    def _apply_order(self,od,side,target):
        if od["kind"]=="damage_line":
            ln=od.get("line","e_front" if side=="p" else "p_front")
            z=self.board[ln]
            if not z: return "无目标"
            t=min(z,key=lambda x:x["def_"])
            t["def_"]-=od["val"]
            nm=t["name"]
            if t["def_"]<=0: z.remove(t); return f"{nm} 被摧毁!"
            return f"对{nm}造成{od['val']}伤害"
        elif od["kind"]=="damage_any":
            if not target: return "无目标"
            _,ln,i,_=target
            z=self.board[ln]
            if i>=len(z): return "目标消失"
            z[i]["def_"]-=od["val"]
            nm=z[i]["name"]
            if z[i]["def_"]<=0: z.pop(i); return f"{nm} 被摧毁!"
            return f"对{nm}造成{od['val']}伤害"
        elif od["kind"]=="damage_hq":
            if side=="p":
                self.enemy_hq-=od["val"]
                if self.enemy_hq<=0: self.game_over=True; self.winner="player"
            else:
                self.player_hq-=od["val"]
                if self.player_hq<=0: self.game_over=True; self.winner="enemy"
            return f"总部-{od['val']}"
        elif od["kind"]=="draw":
            if side=="p":
                for _ in range(min(od["val"],len(self.player_deck))):
                    if self.player_deck:
                        self.player_hand.append(self.player_deck.pop())
                        if len(self.player_hand)>HAND_LIMIT: self.player_hand.pop()
            else:
                for _ in range(min(od["val"],len(self.enemy_deck))):
                    if self.enemy_deck: self.enemy_hand.append(self.enemy_deck.pop())
            return f"抽{od['val']}张"
        elif od["kind"]=="summon":
            ln=od.get("line","p_front" if side=="p" else "e_front")
            if len(self.board[ln])>=ZONE_CAP: return "阵线满"
            u=make_unit("援军",0,od.get("a",1),od.get("d",1),0,od.get("unit","infantry"),"通用",[],"🪖")
            u["summoned_this_turn"]=True
            self.board[ln].append(u)
            return f"召唤{u['name']}"
        elif od["kind"]=="summon_multi":
            ln="p_front" if side=="p" else "e_front"
            cnt=0
            for _ in range(od.get("count",1)):
                if len(self.board[ln])>=ZONE_CAP: break
                u=make_unit("伞兵",0,od.get("a",1),od.get("d",1),1,"infantry","通用",["airborne"],"🪖")
                u["summoned_this_turn"]=True
                self.board[ln].append(u)
                cnt+=1
            return f"召唤{cnt}个单位"
        elif od["kind"]=="heal":
            if not target: return "无目标"
            _,ln,i,_=target
            z=self.board[ln]
            if i>=len(z): return "目标消失"
            z[i]["def_"]=min(z[i].get("max_def",z[i]["def_"]),z[i]["def_"]+od["val"])
            return f"恢复{od['val']}防御"
        elif od["kind"]=="buff":
            if not target: return "无目标"
            _,ln,i,_=target
            z=self.board[ln]
            if i>=len(z): return "目标消失"
            z[i]["atk"]+=od.get("atk_bonus",0)
            z[i]["def_"]+=od.get("def_bonus",0)
            if od.get("temp"): z[i]["atk"]=min(z[i]["atk"],z[i].get("max_def",10))
            return f"攻+{od.get('atk_bonus',0)} 防+{od.get('def_bonus',0)}"
        elif od["kind"]=="buff_all":
            for ln2 in ("p_front","p_support") if side=="p" else ("e_front","e_support"):
                for u in self.board[ln2]:
                    u["def_"]+=od.get("def_bonus",0)
            return f"全体防御+{od.get('def_bonus',0)}"
        elif od["kind"]=="disable":
            if not target: return "无目标"
            _,ln,i,_=target
            z=self.board[ln]
            if i>=len(z): return "目标消失"
            z[i]["attacked_this_turn"]=True
            return f"{z[i]['name']} 本回合无法攻击"
        elif od["kind"]=="damage_all":
            cnt=0
            for ln2 in ("e_front","e_support") if side=="p" else ("p_front","p_support"):
                for u in self.board[ln2]:
                    u["def_"]-=od["val"]
                    cnt+=1
                self.board[ln2]=[u for u in self.board[ln2] if u["def_"]>0]
            return f"对{cnt}个单位造成{od['val']}伤害"
        elif od["kind"]=="damage_air":
            cnt=0
            for ln2 in ("e_front","e_support") if side=="p" else ("p_front","p_support"):
                for u in list(self.board[ln2]):
                    if u.get("unit") in ("fighter","bomber"):
                        u["def_"]-=od["val"]
                        cnt+=1
            return f"对{cnt}个空军造成{od['val']}伤害"
        return "未知指令"

    def _japanese_last_stand(self):
        all_e=[]
        for ln in ("e_front","e_support"):
            for i,u in enumerate(self.board[ln]):
                all_e.append((ln,i,u))
        if all_e:
            ln,i,u=random.choice(all_e)
            u["def_"]-=1
            self.log_msg(f"🔥 玉碎：{u['name']} -1")
            if u["def_"]<=0:
                self.board[ln].pop(i)
                self.log_msg(f"💀 {u['name']} 被玉碎摧毁")

    def end_turn_player(self):
        if self.phase!="play": return False,"不是你的回合"
        self.phase="enemy_turn"
        self.log_msg("—— 你的回合结束 ——")
        return True,""

    def start_next_turn(self):
        self.turn+=1
        self.cp_cap=min(MAX_CP,self.cp_cap+1)
        self.player_cp=self.cp_cap
        self.enemy_cp=self.cp_cap
        # 抽牌
        if self.go_first or self.turn>1:
            if self.player_deck:
                self.player_hand.append(self.player_deck.pop())
                if len(self.player_hand)>HAND_LIMIT: self.player_hand.pop()
            else:
                self.player_hq-=self.fatigue
                self.log_msg(f"💔 疲劳伤害 {self.fatigue}!")
                self.fatigue+=1
                if self.player_hq<=0: self.game_over=True; self.winner="enemy"
        if self.enemy_deck:
            self.enemy_hand.append(self.enemy_deck.pop())
        else:
            self.enemy_hq-=self.fatigue
            if self.enemy_hq<=0: self.game_over=True; self.winner="player"
        # 美国加成
        if self.player=="美国" and self.turn>=3 and self.player_deck:
            self.player_hand.append(self.player_deck.pop())
        # 重置单位
        for ln in ("p_front","p_support","e_front","e_support"):
            for u in self.board[ln]:
                if u["type"]=="unit":
                    u["moved_this_turn"]=False
                    u["attacked_this_turn"]=False
                    u["summoned_this_turn"]=False
                    u["mov_remaining"]=u.get("mov",1)
        self.german_move_used=False
        self.phase="play"
        self.selected=None
        self.pending_action=None
        self.log_msg(f"🌀 回合{self.turn} 指挥点{self.cp_cap}")

# ============================================================
# AI
# ============================================================
class EnemyAI:
    def __init__(self,S):
        self.S=S

    def take_turn(self):
        actions=[]
        # 1. 指令
        for i in range(len(self.S.enemy_hand)-1,-1,-1):
            c=self.S.enemy_hand[i]
            if c["type"]!="order": continue
            if self.S.enemy_cp<c["cost"]: continue
            od=c["data"]
            if od["kind"]=="damage_hq" and self.S.player_hq<=10:
                actions.append(("order",i,None)); break
            elif od["kind"] in ("draw","summon"):
                actions.append(("order",i,None))
            elif od["kind"] in ("damage_any","damage_line","heal","buff"):
                best=None;bs=-1
                for ln in ("p_front","p_support"):
                    for j,u in enumerate(self.S.board[ln]):
                        sc=u.get("atk",0)*2+u.get("def_",0)
                        if sc>bs: bs=sc; best=("unit",ln,j,u)
                if best: actions.append(("order",i,best))

        # 2. 部署
        for i in range(len(self.S.enemy_hand)-1,-1,-1):
            c=self.S.enemy_hand[i]
            if c["type"]!="unit": continue
            if self.S.enemy_cp<c["cost"]: continue
            if len(self.S.board["e_front"])<ZONE_CAP:
                actions.append(("deploy",i,"front"))
            elif len(self.S.board["e_support"])<ZONE_CAP and c.get("def_",0)>=4:
                actions.append(("deploy",i,"support"))

        # 3. 移动
        if not self.S.board["e_front"]:
            for i,u in enumerate(self.S.board["e_support"]):
                if u.get("mov_remaining",0)>0:
                    actions.append(("move",i,"support","front")); break

        # 4. 攻击
        for i,u in enumerate(self.S.board["e_front"]):
            if u.get("attacked_this_turn"): continue
            if u.get("summoned_this_turn") and "blitz" not in u.get("keywords",[]): continue
            tgts=self.S.get_valid_targets(u,"e","front")
            if not tgts: continue
            best=None;bs=-1
            for tt,tln,ti,tc in tgts:
                if tt=="hq":
                    if self.S.player_hq<=4: best=(tt,tln,ti,tc); break
                    continue
                sc=tc.get("atk",0)*2+tc.get("def_",0)
                if sc>bs: bs=sc; best=(tt,tln,ti,tc)
            if best:
                if best[0]=="hq":
                    actions.append(("attack_hq",i,"front","e"))
                else:
                    actions.append(("attack",i,"front",best[1],best[2]))

        return actions

# ============================================================
# UI
# ============================================================
root=tk.Tk()
root.title("🎖️ KARDS - 二战卡牌对战（完整版）")
root.geometry("1280x920")
root.configure(bg="#0d1b2a")

S=GameState()
ui_refs={}

def draw_card(canvas,card,x,y,selected=False,highlight=False):
    w,h=CARD_W,CARD_H
    out="#ffd700" if selected else ("#00ff88" if highlight else "#333")
    wid=3 if (selected or highlight) else 2
    canvas.create_rectangle(x,y,x+w,y+h,fill="#f0ede6",outline=out,width=wid,tags="card")
    if card["type"]=="unit":
        fc=FACTIONS.get(card.get("faction","苏联"),{"color":"#666"})["color"]
        canvas.create_rectangle(x+2,y+2,x+w-2,y+18,fill=fc,outline="")
        canvas.create_text(x+w/2,y+28,text=f"{card.get('icon','')}{card['name']}",font=("Microsoft YaHei",8,"bold"),fill="#111",tags="card")
        canvas.create_text(x+w/2,y+44,text=card.get("unit",""),font=("Microsoft YaHei",7),fill="#666",tags="card")
        canvas.create_rectangle(x+4,y+h-26,x+w/2-2,y+h-4,fill="#2a9d8f",tags="card")
        canvas.create_text(x+w/4,y+h-15,text=f"⚔{card['atk']}",font=("Microsoft YaHei",10,"bold"),fill="white",tags="card")
        canvas.create_rectangle(x+w/2+2,y+h-26,x+w-4,y+h-4,fill="#e76f51",tags="card")
        canvas.create_text(x+3*w/4,y+h-15,text=f"🛡{card['def_']}",font=("Microsoft YaHei",10,"bold"),fill="white",tags="card")
        canvas.create_text(x+10,y+h-34,text=f"🎟{card['cost']}",font=("Microsoft YaHei",8,"bold"),fill="#e9c46a",tags="card")
        mr=card.get("mov_remaining",card.get("mov",1))
        canvas.create_text(x+10,y+h-46,text=f"➡{mr}",font=("Microsoft YaHei",8),fill="#457b9d",tags="card")
        kws=card.get("keywords",[])
        if kws:
            canvas.create_text(x+w/2,y+h-54,text=",".join(kws[:2]),font=("Microsoft YaHei",6),fill="#9b59b6",tags="card")
    else:
        canvas.create_rectangle(x+2,y+2,x+w-2,y+18,fill="#8e44ad",outline="")
        canvas.create_text(x+w/2,y+20,text="📜",font=("Microsoft YaHei",16),tags="card")
        canvas.create_text(x+w/2,y+42,text=card["name"],font=("Microsoft YaHei",8,"bold"),fill="#111",tags="card")
        for li,ln in enumerate(card.get("desc","").split("\n")[:3]):
            canvas.create_text(x+w/2,y+58+li*13,text=ln,font=("Microsoft YaHei",7),fill="#555",tags="card")
        canvas.create_text(x+10,y+h-12,text=f"🎟{card['cost']}",font=("Microsoft YaHei",8,"bold"),fill="#e9c46a",tags="card")

def render_zone(canvas,zone,side,line,click_cb):
    x=10
    for i,c in enumerate(zone):
        sel=S.selected==(f"{side}_{line}",i)
        hl=False
        if S.pending_action and S.pending_action.get("kind")=="target":
            if (side,line,i) in S.pending_action.get("targets",[]):
                hl=True
        y=8
        col="#2a6fbb" if side=="p" else "#b53a3a"
        canvas.create_rectangle(x,y,x+CARD_W-12,y+CARD_H-30,fill=col,
            outline="#ffd700" if sel else ("#00ff88" if hl else "#111"),
            width=3 if sel else (2 if hl else 1),tags="card")
        canvas.create_text(x+(CARD_W-12)/2,y+14,text=f"{c.get('icon','')}{c['name']}",
            font=("Microsoft YaHei",7,"bold"),fill="white",tags="card")
        canvas.create_text(x+12,y+CARD_H-46,text=f"⚔{c.get('atk',0)}",font=("Microsoft YaHei",8,"bold"),fill="#ffd700",tags="card")
        canvas.create_text(x+(CARD_W-12)-12,y+CARD_H-46,text=f"🛡{c.get('def_',0)}",font=("Microsoft YaHei",8,"bold"),fill="#a8e6cf",tags="card")
        if sel:
            canvas.create_text(x+(CARD_W-12)/2,y-4,text="◀",font=("Microsoft YaHei",8,"bold"),fill="#ffd700",tags="card")
        canvas.tag_bind("card","<Button-1>",lambda e,idx=i:click_cb(line,idx))
        x+=CARD_W-4

# ============ 界面切换 ============
def show_faction():
    for w in root.winfo_children(): w.destroy()
    root.configure(bg="#0d1b2a")
    frm=tk.Frame(root,bg="#0d1b2a")
    frm.pack(expand=True,fill="both",padx=80,pady=30)

    tk.Label(frm,text="🎖️ KARDS",font=("Microsoft YaHei",52,"bold"),fg="#e63946",bg="#0d1b2a").pack(pady=6)
    tk.Label(frm,text="二战题材 · 完整策略卡牌对战",font=("Microsoft YaHei",14),fg="#a8dadc",bg="#0d1b2a").pack(pady=2)

    pf=tk.StringVar(value="苏联")
    af=tk.StringVar(value="无")

    cf=tk.LabelFrame(frm,text="⚔ 选择主阵营",bg="#1b263b",fg="white",font=("Microsoft YaHei",12,"bold"))
    cf.pack(fill="x",pady=14)
    ttk.Combobox(cf,textvariable=pf,values=list(FACTIONS.keys()),state="readonly",font=("Microsoft YaHei",11)).pack(padx=14,pady=8)
    bonus_lbl=tk.Label(cf,text="",font=("Microsoft YaHei",9),fg="#ffd700",bg="#1b263b")
    bonus_lbl.pack(pady=2)
    def upd(*a): bonus_lbl.config(text=FACTIONS[pf.get()]["bonus"])
    pf.trace_add("write",upd); upd()

    ca=tk.LabelFrame(frm,text="🤝 盟国（可选，≤12张）",bg="#1b263b",fg="white",font=("Microsoft YaHei",12,"bold"))
    ca.pack(fill="x",pady=8)
    ttk.Combobox(ca,textvariable=af,values=["无"]+list(FACTIONS.keys()),state="readonly",font=("Microsoft YaHei",11)).pack(padx=14,pady=8)

    rules_txt=("📋 规则：40张卡组·盟国≤12·CP每回合+1(上限12)·总部20HP(+法国+3)\n"
               "前线未清空→无法攻击支援/总部·部署当回合不可攻击(闪击除外)\n"
               "关键词：闪击/装甲/穿甲/防空/飞行/远程/守卫/激励/伏击/杀回\n"
               "疲劳递增·手牌上限10·每线5单位·6阵营专属卡+通用指令")
    tk.Label(frm,text=rules_txt,font=("Microsoft YaHei",10),fg="#778da9",bg="#0d1b2a",justify="left").pack(pady=14)

    def start(gf):
        ally=None if af.get()=="无" else af.get()
        S.start_match(pf.get(),ally,gf)
        build_game_ui()
        if not gf:
            root.after(1200,enemy_turn_seq)

    tk.Button(frm,text="▶ 开始（我方先手）",font=("Microsoft YaHei",14,"bold"),bg="#e63946",fg="white",padx=24,pady=10,command=lambda:start(True)).pack(pady=6)
    tk.Button(frm,text="开始后手（敌方先攻）",font=("Microsoft YaHei",12),bg="#457b9d",fg="white",padx=18,pady=7,command=lambda:start(False)).pack(pady=3)

def build_game_ui():
    for w in root.winfo_children(): w.destroy()
    root.configure(bg="#1a1a1a")

    top=tk.Frame(root,bg="#1d3557",height=40)
    top.pack(fill="x")
    ui_refs["turn"]=tk.Label(top,text="",font=("Microsoft YaHei",13,"bold"),fg="white",bg="#1d3557")
    ui_refs["turn"].pack(side="left",padx=16)
    ui_refs["info"]=tk.Label(top,text="",font=("Microsoft YaHei",10),fg="#a8dadc",bg="#1d3557")
    ui_refs["info"].pack(side="left",padx=24)

    bf=tk.Frame(root,bg="#1a1a1a")
    bf.pack(fill="both",expand=True,padx=10,pady=4)

    # 敌方支援
    esf=tk.LabelFrame(bf,text="敌方支援",bg="#3a0d0d",fg="#ff6b6b",font=("Microsoft YaHei",9,"bold"))
    esf.pack(fill="x",padx=6,pady=2)
    ui_refs["e_sup"]=tk.Canvas(esf,width=1200,height=82,bg="#2a0808",highlightthickness=0)
    ui_refs["e_sup"].pack(fill="x")

    # 敌方前线
    eff=tk.LabelFrame(bf,text="敌方前线",bg="#4a1a1a",fg="#ff9999",font=("Microsoft YaHei",9,"bold"))
    eff.pack(fill="x",padx=6,pady=2)
    ui_refs["e_fr"]=tk.Canvas(eff,width=1200,height=82,bg="#3a1010",highlightthickness=0)
    ui_refs["e_fr"].pack(fill="x")

    # 敌方总部
    ehqf=tk.Frame(bf,bg="#4a0a0a"); ehqf.pack(fill="x",padx=6,pady=2)
    ui_refs["ehq"]=tk.Label(ehqf,text="🏰 敌方总部 ❤️20",font=("Microsoft YaHei",13,"bold"),fg="#ffcc00",bg="#4a0a0a")
    ui_refs["ehq"].pack(side="left",padx=14)

    # 中线
    vsf=tk.Frame(bf,bg="#1a1a1a",height=22); vsf.pack(fill="x")
    tk.Label(vsf,text="⚔️ ──── 战 场 中 线 ──── ⚔️",font=("Microsoft YaHei",10),fg="#555",bg="#1a1a1a").pack()

    # 我方总部
    phqf=tk.Frame(bf,bg="#0a3a0a"); phqf.pack(fill="x",padx=6,pady=2)
    ui_refs["phq"]=tk.Label(phqf,text="🏰 我方总部 ❤️20",font=("Microsoft YaHei",13,"bold"),fg="#66ff66",bg="#0a3a0a")
    ui_refs["phq"].pack(side="left",padx=14)

    # 我方前线
    pff=tk.LabelFrame(bf,text="我方前线",bg="#1a4a1a",fg="#99ff99",font=("Microsoft YaHei",9,"bold"))
    pff.pack(fill="x",padx=6,pady=2)
    ui_refs["p_fr"]=tk.Canvas(pff,width=1200,height=82,bg="#103010",highlightthickness=0)
    ui_refs["p_fr"].pack(fill="x")

    # 我方支援
    psf=tk.LabelFrame(bf,text="我方支援",bg="#0d3a0d",fg="#66cc66",font=("Microsoft YaHei",9,"bold"))
    psf.pack(fill="x",padx=6,pady=2)
    ui_refs["p_sup"]=tk.Canvas(psf,width=1200,height=82,bg="#082008",highlightthickness=0)
    ui_refs["p_sup"].pack(fill="x")

    # 手牌
    hf=tk.LabelFrame(root,text="🃏 手牌（点击选择→点击战场操作）",bg="#16213e",fg="white",font=("Microsoft YaHei",11,"bold"))
    hf.pack(fill="x",padx=10,pady=3)
    ui_refs["hand"]=tk.Canvas(hf,width=1200,height=158,bg="#0f1b33",highlightthickness=0)
    ui_refs["hand"].pack(fill="x")

    # 按钮
    bb=tk.Frame(root,bg="#1a1a1a"); bb.pack(fill="x",padx=10,pady=5)
    tk.Button(bb,text="🔚 结束回合",font=("Microsoft YaHei",12,"bold"),bg="#e63946",fg="white",command=on_end_turn).pack(side="left",padx=6)
    tk.Button(bb,text="🎯 取消",command=on_cancel).pack(side="left",padx=6)
    tk.Button(bb,text="🔄 重开",command=show_faction).pack(side="left",padx=6)

    # 日志
    lf=tk.LabelFrame(root,text="📜 战报",bg="#111",fg="#aaa",font=("Microsoft YaHei",10,"bold"))
    lf.pack(fill="x",padx=10,pady=3)
    ui_refs["log"]=tk.Text(lf,height=5,width=120,bg="#0a0a0a",fg="#ccc",font=("Consolas",10),state="disabled")
    ui_refs["log"].pack(fill="x",padx=6,pady=4)

    refresh()

def refresh():
    if S.game_over:
        pass
    ui_refs["turn"].config(text=f"⚔ 回合{S.turn} · {'🟢你的回合' if S.phase=='play' else '🔴敌方行动'}")
    ui_refs["info"].config(text=f"CP {S.player_cp}/{S.cp_cap} · 牌库{len(S.player_deck)} · 手牌{len(S.player_hand)}/10")
    ui_refs["ehq"].config(text=f"🏰 敌方总部 ❤️{max(0,S.enemy_hq)}")
    ui_refs["phq"].config(text=f"🏰 我方总部 ❤️{max(0,S.player_hq)}")

    for key,cvkey in [("e_support","e_sup"),("e_front","e_fr"),("p_front","p_fr"),("p_support","p_sup")]:
        cv=ui_refs[cvkey]; cv.delete("all")
        sd="p" if key.startswith("p") else "e"
        ln=key.split("_")[1]
        render_zone(cv,S.board[key],sd,ln,on_zone_click)

    hcv=ui_refs["hand"]; hcv.delete("all")
    x=8
    for i,c in enumerate(S.player_hand):
        sel=S.selected==("hand",i)
        draw_card(hcv,c,x,6,selected=sel)
        hcv.tag_bind("card","<Button-1>",lambda e,idx=i:on_hand(i))
        x+=CARD_W+8

    lw=ui_refs["log"]; lw.config(state="normal"); lw.delete("1.0","end")
    for l in S.log[-15:]: lw.insert("end",l+"\n")
    lw.config(state="disabled"); lw.see("end")

    if S.player_hq<=0 or S.enemy_hq<=0:
        S.game_over=True
        msg="🎉 你赢了！" if S.enemy_hq<=0 else "💀 敌方赢了！"
        messagebox.showinfo("对局结束",msg)

# ============ 交互 ============
def on_hand(idx):
    if S.phase!="play" or S.game_over: return
    c=S.player_hand[idx]
    if c["type"]=="order":
        S.selected=("hand",idx)
        od=c["data"]
        if od["kind"] in ("damage_any","heal","buff","disable"):
            S.pending_action={"kind":"target","targets":[]}
            for ln in ("p_front","p_support","e_front","e_support"):
                for i,u in enumerate(S.board[ln]):
                    sd="p" if ln.startswith("p") else "e"
                    ll=ln.split("_")[1]
                    S.pending_action["targets"].append((sd,ll,i))
            S.log_msg(f"选择目标：{c['name']}")
        else:
            ok,msg=S.use_order(idx,"p"); S.log_msg(msg); S.selected=None
    else:
        if S.player_cp>=c["cost"]:
            S.selected=("hand",idx)
            S.pending_action={"kind":"deploy"}
            S.log_msg(f"部署 {c['name']} →点击前线/支援")
        else:
            S.log_msg("⚠ CP不足")
    refresh()

def on_zone_click(line,idx):
    if S.phase!="play" or S.game_over: return
    sel=S.selected
    if not sel: return

    if sel[0]=="hand":
        if S.pending_action and S.pending_action.get("kind")=="deploy":
            ok,msg=S.deploy(sel[1],line,"p")
            if ok: S.selected=None; S.pending_action=None
            S.log_msg(msg)
        elif S.pending_action and S.pending_action.get("kind")=="target":
            # 找目标
            for sd,ll,i in S.pending_action["targets"]:
                if ll==line and i==idx:
                    ok,msg=S.use_order(sel[1],"p",("unit",f"{sd}_{ll}",i,S.board[f"{sd}_{ll}"][i]))
                    S.log_msg(msg); S.selected=None; S.pending_action=None; break
    elif sel[0].startswith("p_"):
        sline=sel[0].split("_")[1]
        if sline==line:
            S.selected=None
        else:
            ok,msg=S.move(sline,line,sel[1],"p")
            if ok: S.selected=None
            S.log_msg(msg)
    else:
        # 攻击
        if sel[0].startswith("p_"):
            aline=sel[0].split("_")[1]
            c=S.board[f"p_{aline}"][sel[1]]
            if "blitz" not in c.get("keywords",[]) and c.get("summoned_this_turn"):
                S.log_msg("⚠ 刚部署无法攻击")
            else:
                ok,msg=S.attack_unit("p",aline,sel[1],"e",line,idx)
                if ok: S.selected=None
            S.log_msg(msg)
    refresh()

def on_end_turn():
    if S.phase!="play" or S.game_over: return
    S.end_turn_player()
    S.selected=None; S.pending_action=None
    refresh()
    if not S.game_over and S.phase=="enemy_turn":
        root.after(800,enemy_turn_seq)

def on_cancel():
    S.selected=None; S.pending_action=None; refresh()

def enemy_turn_seq():
    if S.game_over: return
    S.log_msg("🤖 ── 敌方回合 ──"); refresh()
    ai_engine=EnemyAI(S)
    acts=ai_engine.take_turn()

    def do_step(n=0):
        if n>=len(acts) or S.game_over:
            S.start_next_turn(); refresh()
            return
        a=acts[n]
        if a[0]=="deploy": _,hi,ln=a; S.deploy(hi,ln,"e")
        elif a[0]=="move": _,i,fl,tl=a; S.move(fl,tl,i,"e")
        elif a[0]=="attack": _,ai2,al,ti,tl=a; S.attack_unit("e",al,ai2,"p",ti,tl)
        elif a[0]=="attack_hq": _,ai2,al,ts=a; S.attack_hq_act("e",al,ai2,ts)
        elif a[0]=="order": _,hi,tgt=a; S.use_order(hi,"e",tgt)
        refresh()
        root.after(700,lambda:do_step(n+1))

    root.after(500,lambda:do_step(0))

# ============ 启动 ============
show_faction()
root.mainloop()