package taurus.util;

import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TArray;
import robot.mj.handler.HuNanPaoDeKuai;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 湖南跑得快智能出牌算法（全新智能化版本）
 * 特色：动态分析 + 策略自适应 + 全面局势感知
 * 解决原版死板出牌问题，实现真正的智能决策
 */
public class test_smart {
    // ====================== 牌型常量 ======================
    public static final int TYPE_SINGLE = 1;      
    public static final int TYPE_PAIR = 2;        
    public static final int TYPE_STRAIGHT = 3;    
    public static final int TYPE_CONSECUTIVE_PAIR = 4;
    public static final int TYPE_TRIO = 5;        
    public static final int TYPE_TRIO_WITH_TWO = 7;
    public static final int TYPE_BOMB = 8;        
    public static final int TYPE_AIRPLANE = 9;    
    public static final int TYPE_AIRPLANE_WITH_CARDS = 10;
    public static final int TYPE_FOUR_WITH_TWO = 11;
    public static final int TYPE_FOUR_WITH_TWO_PAIR = 12;

    // 牌值定义
    private static final int CARD_3 = 3;
    private static final int CARD_4 = 4;
    private static final int CARD_5 = 5;
    private static final int CARD_6 = 6;
    private static final int CARD_7 = 7;
    private static final int CARD_8 = 8;
    private static final int CARD_9 = 9;
    private static final int CARD_10 = 10;
    private static final int CARD_J = 11;
    private static final int CARD_Q = 12;
    private static final int CARD_K = 13;
    private static final int CARD_A = 14;
    private static final int CARD_2 = 15;

    // 策略常量
    private static final int MIN_STRAIGHT_LENGTH = 5;
    private static final int MIN_CONSECUTIVE_PAIR_COUNT = 2;
    private static final int MIN_AIRPLANE_TRIO_COUNT = 2;
    private static final int THINK_TIMEOUT_SECONDS = 3;

    // ====================== 主入口方法 ======================
    public static ITArray intelligentPaoDeKuaiOutCard(
            HuNanPaoDeKuai huNanPaoDeKuai,
            List<CardObj> cardInhand,
            ITObject card_list,
            Map<Integer, List<Integer>> seatRemainHistory) {

        // 空值校验
        if (cardInhand == null || cardInhand.isEmpty()) {
            System.err.println("[跑得快AI] 手牌为空，返回空出牌指令");
            return new TArray();
        }

        // 超时保护
        ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r);
            t.setName("PaoDeKuai-AI-Thread");
            t.setDaemon(true);
            return t;
        });

        Future<ITArray> future = executor.submit(() -> {
            try {
                ITArray outCards = coreOutCardLogic(huNanPaoDeKuai, cardInhand, card_list, seatRemainHistory);
                if (outCards != null) {
                    if (isIllegalTrioWithOne(outCards)) {
                        System.err.println("[跑得快AI] 检测到非法三带一牌型，重新选择出牌");
                        return reselectLegalCards(cardInhand);
                    }
                }
                return outCards == null ? new TArray() : outCards;
            } catch (Exception e) {
                System.err.println("[跑得快AI] 核心逻辑异常: " + e.getMessage());
                e.printStackTrace();
                return emergencyOutCard(cardInhand);
            }
        });

        try {
            ITArray result = future.get(THINK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
            executor.shutdownNow();
            return result;
        } catch (TimeoutException e) {
            System.err.println("[跑得快AI] 思考超时，执行紧急合法出牌");
            future.cancel(true);
            executor.shutdownNow();
            return emergencyOutCard(cardInhand);
        } catch (Exception e) {
            System.err.println("[跑得快AI] 执行流程异常: " + e.getMessage());
            e.printStackTrace();
            executor.shutdownNow();
            return emergencyOutCard(cardInhand);
        }
    }

    // ====================== 核心出牌逻辑 ======================
    private static ITArray coreOutCardLogic(
            HuNanPaoDeKuai huNanPaoDeKuai,
            List<CardObj> cardInhand,
            ITObject card_list,
            Map<Integer, List<Integer>> seatRemainHistory) {

        // 预处理
        List<CardObj> sortedHand = new ArrayList<>(cardInhand);
        Collections.sort(sortedHand);
        int currentSeat = huNanPaoDeKuai != null ? huNanPaoDeKuai.seat : 0;

        System.out.println("\n========== 湖南跑得快智能出牌（全新版） ==========");
        System.out.println("当前座位: " + currentSeat);
        System.out.println("手牌数量: " + sortedHand.size());
        System.out.println("手牌详情: " + sortedHand.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
        
        // 添加详细的手牌分析
        debugHandAnalysis(sortedHand);

        // 判断出牌模式
        boolean isFirstTurn = isFirstTurn(card_list);
        boolean isReacquireTurn = isReacquirePlayTurn(huNanPaoDeKuai, seatRemainHistory, card_list);

        ITArray outCards;
        if (isFirstTurn) {
            System.out.println("【模式】首轮出牌 - 智能分析决策");
            outCards = handleFirstTurn(sortedHand, seatRemainHistory);
        } else if (isReacquireTurn) {
            System.out.println("【模式】重新获得出牌权 - 智能响应");
            outCards = handleReacquireTurn(sortedHand, seatRemainHistory, currentSeat);
        } else {
            System.out.println("【模式】响应出牌 - 精准匹配");
            outCards = handleResponseTurn(huNanPaoDeKuai, sortedHand, card_list, seatRemainHistory);
        }

        return outCards == null ? new TArray() : outCards;
    }

    // ====================== 模式1：首轮出牌策略 ======================
    private static ITArray handleFirstTurn(List<CardObj> handCards, Map<Integer, List<Integer>> seatRemainHistory) {
        int cardCount = handCards.size();
        System.out.println("\n========== 智能首轮出牌分析 ==========");
        
        // 全面分析
        HandAnalysis analysis = analyzeHandComposition(handCards);
        GameSituation situation = evaluateCurrentSituation(seatRemainHistory);
        
        printHandAnalysis(analysis);
        printSituationAnalysis(situation);
        
        // 综合智能决策
        ITArray decision = makeComprehensiveFirstTurnDecision(handCards, analysis, situation);
        
        System.out.println("[智能决策] 最终出牌: " + getDecisionDescription(decision, handCards));
        return decision;
    }

    // ====================== 模式2：重新获得出牌权 ======================
    private static ITArray handleReacquireTurn(List<CardObj> handCards, Map<Integer, List<Integer>> seatRemainHistory, int currentSeat) {

        // 检查紧急情况
        boolean isOpponentEndgame = checkIfAnyOpponentHasOneCard(seatRemainHistory, currentSeat);
        if (isOpponentEndgame) {
            System.out.println("[残局策略] 检测到对手只剩一张牌");
            return handleEndgameSituation(handCards);
        }
        
        // 检查自身残局状态（手中牌较少时也要谨慎）
        boolean isSelfEndgame = checkIfSelfInEndgame(handCards);
        if (isSelfEndgame) {
            System.out.println("[自我残局] 检测到自身处于残局状态");
            return handleSelfEndgameSituation(handCards);
        }
        
        // 正常情况：智能分析后出牌
        HandAnalysis analysis = analyzeHandComposition(handCards);
        GameSituation situation = evaluateCurrentSituation(seatRemainHistory);
        return makeUniversalDecision(handCards, analysis);
    }

    // ====================== 模式3：响应出牌策略 ======================
    private static ITArray handleResponseTurn(
            HuNanPaoDeKuai huNanPaoDeKuai,
            List<CardObj> handCards,
            ITObject card_list,
            Map<Integer, List<Integer>> seatRemainHistory) {

        try {
            if (card_list == null || !card_list.containsKey("card_list")) {
                System.err.println("[响应出牌] 对手出牌信息为空，返回Pass");
                return new TArray();
            }

            ITArray opponentCardsArray = card_list.getTArray("card_list");
            List<CardObj> opponentCards = CardUtil.toList(opponentCardsArray);
            int minCard = card_list.getInt("min_card");
            int type = card_list.getInt("type");
            int len = card_list.getInt("len");

            System.out.println("对手出牌 - 类型: " + getCardTypeName(type) +
                    ", 最小牌: " + getCardName(minCard) +
                    ", 牌数: " + len);

            // 对手剩余两张牌试探策略
            if (checkIfAnyOpponentHasTwoCards(seatRemainHistory, huNanPaoDeKuai != null ? huNanPaoDeKuai.seat : 0)) {
                System.out.println("【试探策略】对手剩2张牌，谨慎处理对子出牌");
                return handleOpponentTwoCardsResponse(handCards, type, minCard, opponentCards);
            }
            
            // 残局特殊处理
            if (isOpponentEndgame(huNanPaoDeKuai != null ? huNanPaoDeKuai.seat : 0, seatRemainHistory)) {
                System.out.println("【残局策略】对手剩1张牌，智能响应");
                return handleOpponentEndgameResponse(handCards, type, minCard, opponentCards);
            }

            // 正常响应
            List<CardObj> responseCards = findMatchingResponse(handCards, type, minCard, len, opponentCards);

            if (responseCards.isEmpty()) {
                // 跑得快规则：要得起必须出，但优先使用对应牌型
                // 只有在没有对应牌型且没有炸弹时才能PASS
                List<CardObj> bomb = findSmallestBomb(handCards);
                if (!bomb.isEmpty()) {
                    System.out.println("[强制规则] 无对应牌型但有炸弹，必须出炸弹");
                    return CardUtil.toTArray(bomb);
                }
                
                // 无对应牌型且无炸弹，要不起，PASS
                System.out.println("[规则] 无对应牌型且无炸弹，要不起，PASS");
                return new TArray();  // 返回空数组表示PASS
            }

            return CardUtil.toTArray(responseCards);

        } catch (Exception e) {
            System.err.println("[响应出牌] 解析异常: " + e.getMessage());
            e.printStackTrace();
            return emergencyOutCard(handCards);
        }
    }

    // ====================== 智能分析系统 ======================
    
    /** 局势类型枚举 */
    private enum SituationType {
        DOMINANT("主导局面", "我方牌力明显优势"),
        COMPETITIVE("竞争局面", "双方势均力敌"),
        DEFENSIVE("防守局面", "对方牌力较强"),
        ENDGAME("残局阶段", "接近游戏结束"),
        UNCERTAIN("不确定", "信息不足难以判断");
        
        private final String name;
        private final String description;
        
        SituationType(String name, String description) {
            this.name = name;
            this.description = description;
        }
        
        public String getName() { return name; }
        public String getDescription() { return description; }
    }
    
    /** 顺子结构类 */
    private static class StraightStructure {
        List<CardObj> cards;
        int length;
        int minValue;
        int maxValue;
        double qualityScore;        // 质量评分
        double protectionValue;     // 保护价值
        boolean isNested;           // 是否为嵌套结构
        List<StraightStructure> nestedChildren; // 嵌套子结构
        
        StraightStructure(List<CardObj> cards) {
            this.cards = cards;
            this.length = cards.size();
            this.minValue = cards.get(0).cardMod;
            this.maxValue = cards.get(cards.size()-1).cardMod;
            this.qualityScore = calculateQualityScore();
            this.protectionValue = calculateProtectionValue();
            this.isNested = false;
            this.nestedChildren = new ArrayList<>();
        }
        
        private double calculateQualityScore() {
            double score = 0.0;
            // 长度加成
            score += Math.min(length * 0.1, 0.8);
            // 连续性加成
            score += 0.2;
            // 牌值适中加成
            double avgValue = cards.stream().mapToInt(c -> c.cardMod).average().orElse(0);
            if (avgValue >= 6 && avgValue <= 10) score += 0.3; // 中等牌值更优
            return Math.min(score, 1.0);
        }
        
        private double calculateProtectionValue() {
            double value = qualityScore;
            // 嵌套结构额外价值
            if (isNested) value *= 1.5;
            // 长顺子更高保护价值
            if (length >= 8) value *= 1.3;
            return value;
        }
        
        @Override
        public String toString() {
            return String.format("顺子[%d-%d](%d张,质量%.2f,保护%.2f)", 
                minValue, maxValue, length, qualityScore, protectionValue);
        }
    }
    
    /** 连对结构类 */
    private static class ConsecutivePairStructure {
        List<CardObj> cards;
        int pairCount;
        int startValue;
        int endValue;
        double qualityScore;
        double protectionValue;
        
        ConsecutivePairStructure(List<CardObj> cards) {
            this.cards = cards;
            this.pairCount = cards.size() / 2;
            List<Integer> values = cards.stream().map(c -> c.cardMod).distinct().sorted().collect(Collectors.toList());
            this.startValue = values.get(0);
            this.endValue = values.get(values.size()-1);
            this.qualityScore = calculateQualityScore();
            this.protectionValue = calculateProtectionValue();
        }
        
        private double calculateQualityScore() {
            double score = 0.0;
            // 对数加成
            score += Math.min(pairCount * 0.2, 0.8);
            // 连续性加成
            score += 0.2;
            return Math.min(score, 1.0);
        }
        
        private double calculateProtectionValue() {
            return qualityScore * 1.1; // 连对略高于普通顺子
        }
        
        @Override
        public String toString() {
            return String.format("连对[%d-%d](%d对,质量%.2f,保护%.2f)", 
                startValue, endValue, pairCount, qualityScore, protectionValue);
        }
    }
    
    /** 牌优先级指导类 */
    private static class CardPriority {
        String cardType;      // 牌型描述
        int priorityLevel;    // 优先级(1-5, 1最高)
        String reason;        // 推荐理由
        boolean preserveBig;  // 是否建议保留大牌
        
        CardPriority(String cardType, int priorityLevel, String reason, boolean preserveBig) {
            this.cardType = cardType;
            this.priorityLevel = priorityLevel;
            this.reason = reason;
            this.preserveBig = preserveBig;
        }
        
        @Override
        public String toString() {
            return String.format("%s(优先级%d): %s %s", 
                cardType, priorityLevel, reason, preserveBig ? "[保留大牌]" : "");
        }
    }
    
    /** 策略倾向枚举 */
    private enum StrategyTendency {
        AGGRESSIVE("激进型", "主动出击，快速出牌"),
        CONSERVATIVE("保守型", "稳扎稳打，保存实力"),
        BALANCED("均衡型", "攻守兼备，灵活应对"),
        OPPORTUNISTIC("机会型", "等待时机，见机行事"),
        PROGRESSIVE("渐进型", "先小后大，循序渐进"),  // 新增：解决先打大牌问题
        PRESERVATIVE("保存型", "保留关键牌，关键时刻发力");
        
        private final String name;
        private final String description;
        
        StrategyTendency(String name, String description) {
            this.name = name;
            this.description = description;
        }
        
        public String getName() { return name; }
        public String getDescription() { return description; }
    }
    private static class GameSituation {
        int opponentCount;
        List<Integer> opponentSeats;
        Map<Integer, Integer> opponentRemainCards;
        SituationType situationType;
        double pressureLevel;
        double opportunityLevel;
        StrategyTendency tendency;
        
        @Override
        public String toString() {
            return String.format("局势分析: %s | 压力%.2f 机会%.2f | 倾向:%s | 对手剩余:%s",
                situationType.getDescription(), pressureLevel, opportunityLevel, 
                tendency.getDescription(), opponentRemainCards);
        }
    }
    
    /** 潜在结构类 */
    private static class PotentialStructure {
        String type;        // "straight", "consecutive_pair"
        int missingCards;   // 缺少的牌数
        int potentialLength; // 潜在长度
        double formationProbability; // 形成概率
        double valueScore;  // 价值评分
        
        PotentialStructure(String type, int missingCards, int potentialLength) {
            this.type = type;
            this.missingCards = missingCards;
            this.potentialLength = potentialLength;
            this.formationProbability = calculateFormationProbability();
            this.valueScore = calculateValueScore();
        }
        
        private double calculateFormationProbability() {
            // 缺牌越少，形成概率越高
            return Math.max(0.1, 1.0 - missingCards * 0.2);
        }
        
        private double calculateValueScore() {
            double score = 0.0;
            score += potentialLength * 0.1; // 长度价值
            score += formationProbability * 0.5; // 形成概率价值
            score -= missingCards * 0.1; // 缺牌惩罚
            return Math.max(0.0, score);
        }
    }
    
    /** 结构保护计划类 */
    private static class StructureProtectionPlan {
        List<ProtectedStructure> protectedStructures; // 需要保护的结构
        Map<String, Double> protectionPriorities;     // 保护优先级
        List<AlternativeMove> alternativeMoves;       // 替代出牌方案
        
        StructureProtectionPlan() {
            this.protectedStructures = new ArrayList<>();
            this.protectionPriorities = new HashMap<>();
            this.alternativeMoves = new ArrayList<>();
        }
        
        void addProtectedStructure(String type, Object structure, double priority) {
            protectedStructures.add(new ProtectedStructure(type, structure));
            protectionPriorities.put(type, priority);
        }
        
        void addAlternativeMove(String moveType, List<CardObj> cards, double benefitScore, String reason) {
            alternativeMoves.add(new AlternativeMove(moveType, cards, benefitScore, reason));
        }
    }
    
    /** 受保护结构类 */
    private static class ProtectedStructure {
        String type;
        Object structure;
        
        ProtectedStructure(String type, Object structure) {
            this.type = type;
            this.structure = structure;
        }
    }
    
    /** 替代出牌方案类 */
    private static class AlternativeMove {
        String moveType;
        List<CardObj> cards;
        double benefitScore;
        String reason;
        
        AlternativeMove(String moveType, List<CardObj> cards, double benefitScore, String reason) {
            this.moveType = moveType;
            this.cards = cards;
            this.benefitScore = benefitScore;
            this.reason = reason;
        }
    }
    private static class HandAnalysis {
        int totalCards;
        int singleCount;
        int pairCount;
        int trioCount;
        int bombCount;
        int straightCount;
        int consecutivePairCount;
        int airplaneCount;
        
        int lowCards;      // 3-7
        int mediumCards;   // 8-J
        int highCards;     // Q-A,2
        int bigCards;      // K,A,2 (关键大牌)
        
        int maxStraightLength;
        int maxConsecutivePairs;
        boolean hasContinuousStructure;
        
        // 专业级新增字段
        List<StraightStructure> allStraights;           // 所有顺子结构
        List<ConsecutivePairStructure> allConsecutivePairs; // 所有连对结构
        Map<Integer, List<CardObj>> cardGroups;         // 牌值分组
        List<PotentialStructure> potentialStructures;   // 潜在可形成的结构
        StructureProtectionPlan protectionPlan;         // 结构保护计划
        
        double comboQualityScore;
        double flexibilityScore;
        double controlScore;
        double riskScore;
        double vulnerabilityScore;
        
        // 新增的智能评估指标
        double bigCardRatio;        // 大牌比例
        double smallCardRatio;      // 小牌比例
        double balanceScore;        // 牌力平衡度
        double progressionScore;    // 出牌流畅度
        
        // 专业级评估指标
        double structureIntegrityScore;     // 结构完整性评分
        double disruptionCostScore;         // 拆分代价评分
        double futurePotentialScore;        // 未来发展潜力
        double strategicValueScore;         // 战略价值评分
        
        String recommendedStrategy;
        List<String> alternativeStrategies;
        
        // 出牌优先级指导
        List<CardPriority> priorityGuidance;
        
        @Override
        public String toString() {
            return String.format("手牌分析: %d张牌 | 单%d 对%d 三%d 炸%d | 小%d 中%d 大%d 关键%d | 策略:%s | 平衡度:%.2f | 完整性:%.2f",
                totalCards, singleCount, pairCount, trioCount, bombCount,
                lowCards, mediumCards, highCards, bigCards, recommendedStrategy, balanceScore, structureIntegrityScore);
        }
    }
    
    /** 分析手牌构成 */
    private static HandAnalysis analyzeHandComposition(List<CardObj> handCards) {
        HandAnalysis analysis = new HandAnalysis();
        analysis.totalCards = handCards.size();
        analysis.alternativeStrategies = new ArrayList<>();
        
        // 基础统计
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        for (List<CardObj> group : groups.values()) {
            int size = group.size();
            switch (size) {
                case 1: analysis.singleCount++; break;
                case 2: analysis.pairCount++; break;
                case 3: analysis.trioCount++; break;
                case 4: analysis.bombCount++; break;
            }
        }
        
        // 牌力分布（细化分类）
        for (CardObj card : handCards) {
            int value = card.cardMod;
            if (value <= CARD_7) {
                analysis.lowCards++;
            } else if (value <= CARD_J) {
                analysis.mediumCards++;
            } else if (value <= CARD_Q) {
                analysis.highCards++;
            } else {
                analysis.highCards++;
                analysis.bigCards++;  // K,A,2为关键大牌
            }
        }
        
        // 计算新增指标
        analysis.smallCardRatio = (double)(analysis.lowCards + analysis.mediumCards) / analysis.totalCards;
        analysis.bigCardRatio = (double)analysis.bigCards / analysis.totalCards;
        analysis.balanceScore = calculateBalanceScore(analysis);
        analysis.progressionScore = calculateProgressionScore(analysis);
        
        // 连续结构
        analysis.maxStraightLength = findMaxStraightLength(handCards);
        analysis.maxConsecutivePairs = findMaxConsecutivePairs(handCards);
        analysis.hasContinuousStructure = (analysis.maxStraightLength >= 5 || analysis.maxConsecutivePairs >= 2);
        
        // 复合牌型
        analysis.straightCount = findAllStraights(handCards, 5).size();
        analysis.consecutivePairCount = findAllConsecutivePairs(handCards, 2).size();
        analysis.airplaneCount = findAllAirplanesWithCards(handCards, 2).size();
        
        // 质量评估
        analysis.comboQualityScore = calculateComboQuality(analysis);
        analysis.flexibilityScore = calculateFlexibilityScore(analysis);
        analysis.controlScore = calculateControlScore(analysis);
        
        // 风险评估
        analysis.riskScore = calculateRiskScore(analysis);
        analysis.vulnerabilityScore = calculateVulnerabilityScore(analysis);
        
        // 策略推荐
        analysis.recommendedStrategy = recommendAdvancedStrategy(analysis);
        analysis.alternativeStrategies = generateAlternativeStrategies(analysis);
        
        // 生成出牌优先级指导
        analysis.priorityGuidance = generatePriorityGuidance(analysis);
        
        return analysis;
    }
    
    /** 分析游戏局势 */
    private static GameSituation evaluateCurrentSituation(Map<Integer, List<Integer>> seatRemainHistory) {
        GameSituation situation = new GameSituation();
        situation.opponentRemainCards = new HashMap<>();
        situation.opponentSeats = new ArrayList<>();
        
        if (seatRemainHistory == null || seatRemainHistory.isEmpty()) {
            situation.situationType = SituationType.UNCERTAIN;
            situation.pressureLevel = 0.5;
            situation.opportunityLevel = 0.5;
            situation.tendency = StrategyTendency.BALANCED;
            situation.opponentCount = 2;
            return situation;
        }
        
        // 分析对手信息
        int totalOpponents = 0;
        int opponentsWithFewCards = 0;
        int minRemainCards = Integer.MAX_VALUE;
        
        for (Map.Entry<Integer, List<Integer>> entry : seatRemainHistory.entrySet()) {
            List<Integer> remainList = entry.getValue();
            if (remainList != null && !remainList.isEmpty()) {
                int currentRemain = remainList.get(remainList.size() - 1);
                situation.opponentRemainCards.put(entry.getKey(), currentRemain);
                situation.opponentSeats.add(entry.getKey());
                
                totalOpponents++;
                minRemainCards = Math.min(minRemainCards, currentRemain);
                
                if (currentRemain <= 3) {
                    opponentsWithFewCards++;
                }
            }
        }
        
        situation.opponentCount = totalOpponents;
        
        // 局势判断
        if (opponentsWithFewCards > 0) {
            situation.situationType = SituationType.ENDGAME;
            situation.pressureLevel = 0.8;
            situation.opportunityLevel = 0.7;
        } else if (minRemainCards <= 5) {
            situation.situationType = SituationType.COMPETITIVE;
            situation.pressureLevel = 0.6;
            situation.opportunityLevel = 0.5;
        } else {
            situation.situationType = SituationType.COMPETITIVE;
            situation.pressureLevel = 0.5;
            situation.opportunityLevel = 0.5;
        }
        
        situation.tendency = determineStrategyTendency(situation);
        return situation;
    }

    // ====================== 智能决策系统 ======================
    
    /** 综合首轮决策 */
    private static ITArray makeComprehensiveFirstTurnDecision(List<CardObj> handCards, HandAnalysis analysis, GameSituation situation) {
        System.out.println("\n[综合决策] 手牌策略:" + analysis.recommendedStrategy + " | 局势倾向:" + situation.tendency.getName());
        
        ITArray decision = null;
        
        switch (situation.tendency) {
            case AGGRESSIVE:
                decision = makeAggressiveDecision(handCards, analysis, situation);
                break;
            case CONSERVATIVE:
                decision = makeConservativeDecision(handCards, analysis, situation);
                break;
            case OPPORTUNISTIC:
                decision = makeOpportunisticDecision(handCards, analysis, situation);
                break;
            case BALANCED:
            default:
                decision = makeBalancedDecision(handCards, analysis, situation);
                break;
        }
        
        if (decision == null || decision.size() == 0) {
            System.out.println("[备用策略] 特定策略无效，启用通用策略");
            decision = makeUniversalDecision(handCards, analysis);
        }
        
        return decision;
    }
    
    /** 激进型决策 */
    private static ITArray makeAggressiveDecision(List<CardObj> handCards, HandAnalysis analysis, GameSituation situation) {
        System.out.println("[激进策略] 主动出击，优先出大牌组合");
        
        List<CardObj> outCards;
        
        outCards = findBestQualityCombo(handCards, analysis);
        if (!outCards.isEmpty()) {
            System.out.println("[激进] 出高质量组合: " + outCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(outCards);
        }
        
        outCards = findLargestStraight(handCards);
        if (!outCards.isEmpty()) {
            System.out.println("[激进] 出最大顺子: " + outCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(outCards);
        }
        
        outCards = findLargePair(handCards, CARD_10);
        if (!outCards.isEmpty()) {
            System.out.println("[激进] 出大对子: " + outCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(outCards);
        }
        
        return null;
    }
    
    /** 保守型决策 */
    private static ITArray makeConservativeDecision(List<CardObj> handCards, HandAnalysis analysis, GameSituation situation) {
        System.out.println("[保守策略] 稳扎稳打，优先出小牌");
        
        List<CardObj> outCards;
        
        outCards = findSmallComboConservative(handCards);
        if (!outCards.isEmpty()) {
            System.out.println("[保守] 出小牌组合: " + outCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(outCards);
        }
        
        outCards = findSmallPair(handCards, CARD_8);
        if (!outCards.isEmpty()) {
            System.out.println("[保守] 出小对子: " + outCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(outCards);
        }
        
        CardObj smallCard = findSmallCard(handCards, CARD_7);
        if (smallCard != null) {
            System.out.println("[保守] 出小单牌: " + getCardName(smallCard.cardMod));
            return CardUtil.toTArray1(smallCard);
        }
        
        return null;
    }
    
    /** 机会型决策 */
    private static ITArray makeOpportunisticDecision(List<CardObj> handCards, HandAnalysis analysis, GameSituation situation) {
        System.out.println("[机会策略] 等待最佳时机，灵活选择");
        
        List<CardObj> outCards = findOpportunisticBest(handCards, analysis, situation);
        if (!outCards.isEmpty()) {
            System.out.println("[机会] 出最优选择: " + outCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(outCards);
        }
        
        return null;
    }
    
    /** 均衡型决策 */
    private static ITArray makeBalancedDecision(List<CardObj> handCards, HandAnalysis analysis, GameSituation situation) {
        System.out.println("[均衡策略] 综合考虑各方面因素");
        // 暂时回退到原来的决策逻辑，直到专业决策系统完善
        return makeUniversalDecision(handCards, analysis);
    }
    
    /** 通用决策 - 全新智能决策系统 */
    private static ITArray makeUniversalDecision(List<CardObj> handCards, HandAnalysis analysis) {
        System.out.println("[智能决策] 启动基于手牌构成的自适应决策系统");
        
        // 1. 首先进行全面的手牌价值评估
        HandEvaluation evaluation = evaluateHandComprehensively(handCards, analysis);
        
        // 2. 生成多种可行的出牌方案
        List<PlayOption> options = generatePlayOptions(handCards, evaluation);
        
        // 3. 智能评估每个选项的预期收益
        PlayOption bestOption = selectOptimalOption(options, evaluation);
        
        // 4. 执行最优选择
        if (bestOption != null && !bestOption.cards.isEmpty()) {
            System.out.println("[智能选择] 选择策略: " + bestOption.strategyName + 
                             " | 预期收益: " + String.format("%.2f", bestOption.expectedValue) + 
                             " | 出牌: " + bestOption.cards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            return CardUtil.toTArray(bestOption.cards);
        }
        
        // 5. 兜底策略
        return fallbackDecision(handCards);
    }
    
    /** 全面手牌评估 */
    private static HandEvaluation evaluateHandComprehensively(List<CardObj> handCards, HandAnalysis analysis) {
        HandEvaluation eval = new HandEvaluation();
        eval.handCards = handCards;
        eval.analysis = analysis;
        
        // 评估各种维度
        eval.comboPotential = evaluateComboPotential(handCards);
        eval.sequencePotential = evaluateSequencePotential(handCards);
        eval.flexibility = evaluateHandFlexibility(handCards);
        eval.controlStrength = evaluateControlStrength(handCards);
        eval.riskLevel = evaluateRiskLevel(handCards);
        
        // 综合评分
        eval.overallScore = (eval.comboPotential * 0.3 + 
                           eval.sequencePotential * 0.25 + 
                           eval.flexibility * 0.2 + 
                           eval.controlStrength * 0.15 + 
                           (1 - eval.riskLevel) * 0.1);
        
        System.out.println("[手牌评估] 组合潜力:" + String.format("%.2f", eval.comboPotential) + 
                         " | 序列潜力:" + String.format("%.2f", eval.sequencePotential) + 
                         " | 灵活性:" + String.format("%.2f", eval.flexibility) + 
                         " | 控制力:" + String.format("%.2f", eval.controlStrength) + 
                         " | 风险:" + String.format("%.2f", eval.riskLevel) + 
                         " | 综合分:" + String.format("%.2f", eval.overallScore));
        
        return eval;
    }
    
    /** 生成出牌选项 */
    private static List<PlayOption> generatePlayOptions(List<CardObj> handCards, HandEvaluation evaluation) {
        List<PlayOption> options = new ArrayList<>();
        
        // 1. 组合牌型选项
        addComboOptions(options, handCards, evaluation);
        
        // 2. 序列牌型选项
        addSequenceOptions(options, handCards, evaluation);
        
        // 3. 单牌选项
        addSingleCardOptions(options, handCards, evaluation);
        
        // 4. 保守选项
        addConservativeOptions(options, handCards, evaluation);
        
        System.out.println("[选项生成] 共生成" + options.size() + "个出牌选项");
        return options;
    }
    
    /** 选择最优选项 */
    private static PlayOption selectOptimalOption(List<PlayOption> options, HandEvaluation evaluation) {
        if (options.isEmpty()) return null;
        
        // 根据预期价值排序
        return options.stream()
                .max(Comparator.comparingDouble(option -> option.expectedValue))
                .orElse(null);
    }
    
    /** 手牌评估类 */
    private static class HandEvaluation {
        List<CardObj> handCards;
        HandAnalysis analysis;
        double comboPotential;      // 组合潜力
        double sequencePotential;   // 序列潜力
        double flexibility;         // 灵活性
        double controlStrength;     // 控制力
        double riskLevel;           // 风险等级
        double overallScore;        // 综合评分
    }
    
    /** 出牌选项类 */
    private static class PlayOption {
        String strategyName;        // 策略名称
        List<CardObj> cards;        // 出牌
        double expectedValue;       // 预期价值
        double riskCost;           // 风险成本
        String rationale;          // 选择理由
        
        PlayOption(String name, List<CardObj> cards, double value, double risk, String rationale) {
            this.strategyName = name;
            this.cards = cards;
            this.expectedValue = value;
            this.riskCost = risk;
            this.rationale = rationale;
        }
    }
    
    // ====================== 评估函数 ======================
    
    /** 评估组合潜力 */
    private static double evaluateComboPotential(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        double potential = 0.0;
        
        // 三张潜力
        long trios = groups.values().stream().filter(list -> list.size() >= 3).count();
        potential += trios * 0.3;
        
        // 对子潜力
        long pairs = groups.values().stream().filter(list -> list.size() == 2).count();
        potential += pairs * 0.2;
        
        // 炸弹潜力
        long bombs = groups.values().stream().filter(list -> list.size() >= 4).count();
        potential += bombs * 0.4;
        
        return Math.min(potential, 1.0);
    }
    
    /** 评估序列潜力 */
    private static double evaluateSequencePotential(List<CardObj> handCards) {
        List<Integer> values = handCards.stream()
                .map(c -> c.cardMod)
                .distinct()
                .sorted()
                .collect(Collectors.toList());
        
        int maxLength = 0;
        int currentLength = 1;
        
        for (int i = 1; i < values.size(); i++) {
            if (values.get(i) == values.get(i-1) + 1) {
                currentLength++;
                maxLength = Math.max(maxLength, currentLength);
            } else {
                currentLength = 1;
            }
        }
        
        // 顺子潜力
        double straightPotential = maxLength >= 5 ? Math.min((maxLength - 4) * 0.2, 0.6) : 0;
        
        // 连对潜力
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        int consecutivePairs = 0;
        int currentPairs = 0;
        
        for (int i = 3; i <= 14; i++) {
            if (groups.getOrDefault(i, new ArrayList<>()).size() >= 2) {
                currentPairs++;
                consecutivePairs = Math.max(consecutivePairs, currentPairs);
            } else {
                currentPairs = 0;
            }
        }
        
        double pairPotential = consecutivePairs >= 2 ? Math.min((consecutivePairs - 1) * 0.15, 0.4) : 0;
        
        return Math.min(straightPotential + pairPotential, 1.0);
    }
    
    /** 评估手牌灵活性 */
    private static double evaluateHandFlexibility(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 牌型多样性
        long comboTypes = groups.values().stream()
                .collect(Collectors.groupingBy(List::size))
                .size();
        
        double diversityScore = Math.min(comboTypes * 0.2, 0.6);
        
        // 中等牌比例
        long mediumCards = handCards.stream()
                .mapToLong(c -> c.cardMod >= 6 && c.cardMod <= 10 ? 1 : 0)
                .sum();
        double mediumRatio = (double) mediumCards / handCards.size();
        
        return Math.min(diversityScore + mediumRatio * 0.4, 1.0);
    }
    
    /** 评估控制强度 */
    private static double evaluateControlStrength(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 大牌控制力
        long bigCards = handCards.stream()
                .mapToLong(c -> c.cardMod >= CARD_J ? 1 : 0)
                .sum();
        double bigCardRatio = (double) bigCards / handCards.size();
        
        // 炸弹威慑力
        long bombs = groups.values().stream().filter(list -> list.size() >= 4).count();
        double bombPower = bombs * 0.3;
        
        // 三张控制力
        long trios = groups.values().stream().filter(list -> list.size() >= 3).count();
        double trioPower = trios * 0.2;
        
        return Math.min(bigCardRatio * 0.5 + bombPower + trioPower, 1.0);
    }
    
    /** 评估风险等级 */
    private static double evaluateRiskLevel(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 孤立单牌风险
        long singleCards = groups.values().stream().filter(list -> list.size() == 1).count();
        double singleRisk = (double) singleCards / handCards.size();
        
        // 大牌风险
        long bigSingles = handCards.stream()
                .filter(c -> groups.get(c.cardMod).size() == 1)
                .mapToLong(c -> c.cardMod >= CARD_Q ? 1 : 0)
                .sum();
        double bigRisk = (double) bigSingles / handCards.size();
        
        return Math.min(singleRisk * 0.7 + bigRisk * 0.3, 1.0);
    }
    
    // ====================== 选项生成函数 ======================
    
    /** 添加组合牌型选项 */
    private static void addComboOptions(List<PlayOption> options, List<CardObj> handCards, HandEvaluation evaluation) {
        // 飞机
        List<CardObj> airplane = findSmallestAirplaneWithCards(handCards);
        if (!airplane.isEmpty()) {
            double value = 0.8 + evaluation.comboPotential * 0.2;
            double risk = 0.2;
            options.add(new PlayOption("飞机出牌", airplane, value, risk, "高价值组合牌型"));
        }
        
        // 三带二
        List<CardObj> trioWithTwo = findSmallestTrioWithTwo(handCards);
        if (!trioWithTwo.isEmpty()) {
            double value = 0.7 + evaluation.comboPotential * 0.15;
            double risk = 0.15;
            
            // 优化：如果三带二能带走小牌，增加额外价值
            CardObj carryCard = findCarryCardInTrioWithTwo(trioWithTwo, handCards);
            if (carryCard != null && carryCard.cardMod <= CARD_8) {
                value += 0.1; // 带小牌额外加分
                System.out.println("[三带二优化] 携带小牌" + getCardName(carryCard.cardMod) + "，增加出牌价值");
            }
            
            options.add(new PlayOption("三带二", trioWithTwo, value, risk, "中等价值组合"));
        }
        
        // 炸弹
        List<CardObj> bomb = findSmallestBomb(handCards);
        if (!bomb.isEmpty()) {
            // 炸弹价值应该极低，除非特殊情况
            double value = 0.3 + evaluation.controlStrength * 0.1; // 大幅降低基础分
            double risk = 0.1;
            
            // 首轮出牌时几乎禁止使用炸弹
            if (handCards.size() > 8) {
                value *= 0.3; // 手牌多时严重抑制炸弹使用
                System.out.println("[炸弹策略] 首轮手牌较多，严格限制炸弹使用");
            }
            
            // 只有在特殊情况下才考虑炸弹
            boolean shouldUseBomb = false;
            String bombReason = "";
            
            // 情况1：手牌很少（≤3张）且需要快速出完
            if (handCards.size() <= 3) {
                shouldUseBomb = true;
                bombReason = "手牌极少，用于快速结束";
            }
            // 情况2：有绝佳的控制机会
            else if (evaluation.controlStrength > 0.8 && handCards.size() <= 6) {
                shouldUseBomb = true;
                bombReason = "强控制力且手牌较少";
            }
            
            if (shouldUseBomb) {
                System.out.println("[炸弹使用] 特殊情况允许使用炸弹 - 原因:" + bombReason);
                options.add(new PlayOption("炸弹", bomb, value, risk, "特殊情况下的强力手段"));
            } else {
                System.out.println("[炸弹策略] 当前情况不适合使用炸弹，优先考虑其他牌型");
                // 不添加炸弹选项，确保不会被选择
            }
        }
        
        // 对子
        List<CardObj> pair = findSmallestPair(handCards);
        if (!pair.isEmpty()) {
            double value = 0.4 + evaluation.comboPotential * 0.1;
            double risk = 0.1;
            options.add(new PlayOption("对子", pair, value, risk, "基础组合牌型"));
        }
    }
    
    /** 添加序列牌型选项 */
    private static void addSequenceOptions(List<PlayOption> options, List<CardObj> handCards, HandEvaluation evaluation) {
        // 顺子
        List<CardObj> straight = findBestStraightAdaptive(handCards);
        if (!straight.isEmpty()) {
            double value = 0.6 + evaluation.sequencePotential * 0.2;
            double risk = 0.25;
            options.add(new PlayOption("顺子", straight, value, risk, "流畅性好的序列"));
        }
        
        // 连对
        List<CardObj> consecutivePair = findBestConsecutivePairAdaptive(handCards);
        if (!consecutivePair.isEmpty()) {
            double value = 0.5 + evaluation.sequencePotential * 0.15;
            double risk = 0.2;
            options.add(new PlayOption("连对", consecutivePair, value, risk, "连续对子结构"));
        }
    }
    
    /** 添加单牌选项 */
    private static void addSingleCardOptions(List<PlayOption> options, List<CardObj> handCards, HandEvaluation evaluation) {
        List<CardObj> singleCards = handCards.stream()
                .filter(c -> CardUtil.getCardNumMap(handCards).get(c.cardMod) == 1)
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        if (!singleCards.isEmpty()) {
            CardObj smallest = singleCards.get(0);
            double value = 0.2;
            double risk = 0.4 + evaluation.riskLevel * 0.3;
            options.add(new PlayOption("最小单牌", Arrays.asList(smallest), value, risk, "消耗孤立小牌"));
            
            if (singleCards.size() > 1) {
                CardObj largest = singleCards.get(singleCards.size() - 1);
                if (largest.cardMod != smallest.cardMod) {
                    double largeValue = 0.3 + evaluation.controlStrength * 0.2;
                    double largeRisk = 0.3;
                    options.add(new PlayOption("最大单牌", Arrays.asList(largest), largeValue, largeRisk, "展示控制力"));
                }
            }
        }
    }
    
    /** 添加保守选项 */
    private static void addConservativeOptions(List<PlayOption> options, List<CardObj> handCards, HandEvaluation evaluation) {
        // 保守的小牌组合
        List<CardObj> smallCombo = findSmallConservativeCombo(handCards);
        if (!smallCombo.isEmpty()) {
            double value = 0.4;
            double risk = 0.1;
            options.add(new PlayOption("保守组合", smallCombo, value, risk, "稳健的出牌选择"));
        }
    }
    
    /** 自适应寻找最佳顺子 */
    private static List<CardObj> findBestStraightAdaptive(List<CardObj> handCards) {
        List<List<CardObj>> allStraights = findAllStraights(handCards, 5);
        if (allStraights.isEmpty()) return new ArrayList<>();
        
        return allStraights.stream()
                .max(Comparator.comparingInt(straight -> {
                    int length = straight.size();
                    int minValue = straight.stream().mapToInt(c -> c.cardMod).min().orElse(0);
                    // 优先长顺子，但避免过大
                    return length >= 7 ? 100 - minValue : length * 10 - minValue;
                }))
                .orElse(new ArrayList<>());
    }
    
    /** 自适应寻找最佳连对 */
    private static List<CardObj> findBestConsecutivePairAdaptive(List<CardObj> handCards) {
        List<List<CardObj>> allPairs = findAllConsecutivePairs(handCards, 2);
        if (allPairs.isEmpty()) return new ArrayList<>();
        
        return allPairs.stream()
                .max(Comparator.comparingInt(pair -> {
                    int pairCount = pair.size() / 2;
                    int minValue = pair.stream().mapToInt(c -> c.cardMod).min().orElse(0);
                    return pairCount * 5 - minValue;
                }))
                .orElse(new ArrayList<>());
    }
    
    /** 寻找保守的小牌组合 */
    private static List<CardObj> findSmallConservativeCombo(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 寻找小对子
        return groups.entrySet().stream()
                .filter(e -> e.getValue().size() == 2 && e.getKey() <= CARD_8)
                .min(Map.Entry.comparingByKey())
                .map(e -> e.getValue())
                .orElse(new ArrayList<>());
    }

    /** 判断出某张牌是否会破坏组合结构 - 智能化版本（优化版） */
    private static boolean wouldBreakComboStructure(CardObj card, List<CardObj> handCards) {
        int cardValue = card.cardMod;
        
        // 获取出手牌后剩余的手牌
        List<CardObj> remainingCards = new ArrayList<>(handCards);
        remainingCards.remove(card);
        
        // 分析剩余手牌的组合潜力
        ComboPotential potential = analyzeComboPotential(remainingCards);
        
        // 如果剩余手牌仍有良好的组合结构，则可以安全出这张牌
        if (potential.hasGoodStructure()) {
            System.out.println("[组合安全] 出" + getCardName(cardValue) + "后剩余手牌仍保持良好结构");
            return false;
        }
        
        // 检查具体的破坏情况
        boolean affectsStraight = wouldAffectStraightFormation(cardValue, handCards);
        boolean affectsConsecutivePair = wouldAffectConsecutivePairFormation(cardValue, handCards);
        
        if (affectsStraight || affectsConsecutivePair) {
            System.out.println("[组合风险] 出" + getCardName(cardValue) + "会影响组合结构");
            return true;
        }
        
        return false;
    }
    
    /** 检查是否会影响顺子形成（改进版） */
    private static boolean wouldAffectStraightFormation(int cardValue, List<CardObj> handCards) {
        // 检查该牌是否是有效顺子形成的关键牌
        boolean hasPrev = handCards.stream().anyMatch(c -> c.cardMod == cardValue - 1);
        boolean hasNext = handCards.stream().anyMatch(c -> c.cardMod == cardValue + 1);
        boolean hasPrev2 = handCards.stream().anyMatch(c -> c.cardMod == cardValue - 2);
        boolean hasNext2 = handCards.stream().anyMatch(c -> c.cardMod == cardValue + 2);
        
        // 新增：检查是否真的能形成有效顺子（至少5张连续牌）
        if (isValidStraightPossible(handCards, cardValue)) {
            // 只有在真正能形成有效顺子时才认为是关键牌
            if ((hasPrev && hasNext) || (hasPrev && hasPrev2) || (hasNext && hasNext2)) {
                System.out.println("[顺子保护] 牌" + getCardName(cardValue) + "是有效顺子的关键牌");
                return true;
            }
        } else {
            System.out.println("[顺子判断] 牌" + getCardName(cardValue) + "不在有效顺子中，可安全出");
        }
        
        return false;
    }
    
    /** 检查是否会影响连对形成（改进版） */
    private static boolean wouldAffectConsecutivePairFormation(int cardValue, List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 如果该牌值有对子，且相邻牌值也有对子的可能性
        if (groups.get(cardValue) != null && groups.get(cardValue).size() >= 2) {
            boolean prevHasPair = groups.getOrDefault(cardValue - 1, new ArrayList<>()).size() >= 2;
            boolean nextHasPair = groups.getOrDefault(cardValue + 1, new ArrayList<>()).size() >= 2;
            
            // 新增：检查是否真的能形成长连对
            if (isValidConsecutivePairPossible(handCards, cardValue)) {
                if (prevHasPair || nextHasPair) {
                    System.out.println("[连对保护] 牌" + getCardName(cardValue) + "是连对的关键牌");
                    return true;
                }
            } else {
                System.out.println("[连对判断] 牌" + getCardName(cardValue) + "不在有效连对中，可安全出");
            }
        }
        
        return false;
    }
    
    /** 组合潜力分析类 */
    private static class ComboPotential {
        public int straightPotential = 0;      // 顺子潜力
        public int pairPotential = 0;          // 对子潜力
        public int trioPotential = 0;          // 三张潜力
        public int consecutivePairPotential = 0; // 连对潜力
        public int airplanePotential = 0;      // 飞机潜力
        public boolean hasGoodStructure = false; // 是否有良好结构
        
        public boolean hasGoodStructure() {
            // 判断是否有良好的组合结构
            return straightPotential >= 5 || 
                   consecutivePairPotential >= 3 ||
                   airplanePotential >= 1 ||
                   (trioPotential >= 2 && pairPotential >= 2);
        }
        
        @Override
        public String toString() {
            return String.format("组合潜力[顺子:%d, 连对:%d, 飞机:%d, 三张:%d, 对子:%d]", 
                               straightPotential, consecutivePairPotential, 
                               airplanePotential, trioPotential, pairPotential);
        }
    }
    
    /** 分析手牌的组合潜力 */
    private static ComboPotential analyzeComboPotential(List<CardObj> cards) {
        ComboPotential potential = new ComboPotential();
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(cards);
        
        // 计算各种牌型的潜力
        potential.straightPotential = calculateStraightPotential(groups);
        potential.pairPotential = calculatePairPotential(groups);
        potential.trioPotential = calculateTrioPotential(groups);
        potential.consecutivePairPotential = calculateConsecutivePairPotential(groups);
        potential.airplanePotential = calculateAirplanePotential(groups);
        
        return potential;
    }
    
    /** 判断移除某张牌后是否仍能形成有效顺子 */
    private static boolean isValidStraightPossible(List<CardObj> handCards, int removedCardValue) {
        // 获取去除指定牌值后的手牌
        List<CardObj> filteredCards = handCards.stream()
                .filter(c -> c.cardMod != removedCardValue)
                .collect(Collectors.toList());
        
        // 检查是否还能形成至少5张的有效顺子
        List<Integer> values = filteredCards.stream()
                .map(c -> c.cardMod)
                .distinct()
                .sorted()
                .collect(Collectors.toList());
        
        int maxLength = 0;
        int currentLength = 1;
        
        for (int i = 1; i < values.size(); i++) {
            if (values.get(i) == values.get(i-1) + 1) {
                currentLength++;
                maxLength = Math.max(maxLength, currentLength);
            } else {
                currentLength = 1;
            }
        }
        
        boolean result = maxLength >= 5;
        System.out.println("[顺子验证] 移除" + getCardName(removedCardValue) + "后最长顺子:" + maxLength + "张, 有效:" + result);
        return result;
    }
    
    /** 计算顺子潜力 */
    private static int calculateStraightPotential(Map<Integer, List<CardObj>> groups) {
        int maxLength = 0;
        int currentLength = 0;
        
        for (int i = 3; i <= 14; i++) { // 3到A
            if (groups.containsKey(i) && groups.get(i).size() >= 1) {
                currentLength++;
                maxLength = Math.max(maxLength, currentLength);
            } else {
                currentLength = 0;
            }
        }
        
        return maxLength;
    }
    
    /** 计算对子潜力 */
    private static int calculatePairPotential(Map<Integer, List<CardObj>> groups) {
        return (int) groups.values().stream()
                .filter(list -> list.size() >= 2)
                .count();
    }
    
    /** 计算三张潜力 */
    private static int calculateTrioPotential(Map<Integer, List<CardObj>> groups) {
        return (int) groups.values().stream()
                .filter(list -> list.size() >= 3)
                .count();
    }
    
    /** 判断移除某张牌后是否仍能形成有效连对 */
    private static boolean isValidConsecutivePairPossible(List<CardObj> handCards, int removedCardValue) {
        // 获取去除指定牌值后的手牌
        List<CardObj> filteredCards = handCards.stream()
                .filter(c -> c.cardMod != removedCardValue)
                .collect(Collectors.toList());
        
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(filteredCards);
        
        // 检查是否还能形成至少2连对（4张牌）
        int maxConsecutive = 0;
        int currentConsecutive = 0;
        
        for (int i = 3; i <= 14; i++) {
            if (groups.containsKey(i) && groups.get(i).size() >= 2) {
                currentConsecutive++;
                maxConsecutive = Math.max(maxConsecutive, currentConsecutive);
            } else {
                currentConsecutive = 0;
            }
        }
        
        boolean result = maxConsecutive >= 2;
        System.out.println("[连对验证] 移除" + getCardName(removedCardValue) + "后最长连对:" + maxConsecutive + "对, 有效:" + result);
        return result;
    }
    
    /** 计算连对潜力 */
    private static int calculateConsecutivePairPotential(Map<Integer, List<CardObj>> groups) {
        int maxConsecutive = 0;
        int currentConsecutive = 0;
        
        for (int i = 3; i <= 14; i++) {
            if (groups.containsKey(i) && groups.get(i).size() >= 2) {
                currentConsecutive++;
                maxConsecutive = Math.max(maxConsecutive, currentConsecutive);
            } else {
                currentConsecutive = 0;
            }
        }
        
        return maxConsecutive;
    }

    /** 计算飞机潜力 */
    private static int calculateAirplanePotential(Map<Integer, List<CardObj>> groups) {
        int maxConsecutive = 0;
        int currentConsecutive = 0;
        
        for (int i = 3; i <= 14; i++) {
            if (groups.containsKey(i) && groups.get(i).size() >= 3) {
                currentConsecutive++;
                maxConsecutive = Math.max(maxConsecutive, currentConsecutive);
            } else {
                currentConsecutive = 0;
            }
        }
        
        return maxConsecutive >= 2 ? maxConsecutive : 0; // 至少需要2个连续的三张才算飞机
    }

    // ====================== 辅助方法 ======================
    
    /** 残局智能决策 - 核心改进！ */
    private static ITArray handleEndgameSituation(List<CardObj> handCards) {
        System.out.println("[残局智能] 分析手牌构成，优先保留组合牌型");
        
        // 1. 首先检查是否有组合牌型可以出
        List<CardObj> comboMove = findBestEndgameCombo(handCards);
        if (!comboMove.isEmpty()) {
            System.out.println("[残局策略] 优先出组合牌型: " + comboMove.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
            return CardUtil.toTArray(comboMove);
        }
        
        // 2. 如果没有组合牌型，才考虑出单牌
        CardObj maxSingleCard = CardUtil.findMaxSingleCard(handCards);
        if (maxSingleCard != null) {
            System.out.println("[残局策略] 无组合牌型可用，出最大单牌: " + getCardName(maxSingleCard.cardMod));
            return CardUtil.toTArray1(maxSingleCard);
        }
        
        // 3. 兜底
        return emergencyOutCard(handCards);
    }

    /** 残局最佳组合牌选择 */
    private static List<CardObj> findBestEndgameCombo(List<CardObj> handCards) {
        System.out.println("[残局分析] 寻找可用的组合牌型");
        
        List<CardObj> bestCombo = new ArrayList<>();
        int bestScore = 0;
        
        // 评估各种组合牌型的价值（炸弹和四带二优先级降低）
        
        // 1. 飞机带牌
        List<CardObj> airplane = findSmallestAirplaneWithCards(handCards);
        if (!airplane.isEmpty() && airplane.size() > bestScore) {
            bestCombo = airplane;
            bestScore = airplane.size();
            System.out.println("[残局评估] 发现飞机，价值: " + airplane.size());
        }
        
        // 2. 三带二
        List<CardObj> trioWithTwo = findSmallestTrioWithTwo(handCards);
        if (!trioWithTwo.isEmpty() && trioWithTwo.size() > bestScore) {
            bestCombo = trioWithTwo;
            bestScore = trioWithTwo.size();
            System.out.println("[残局评估] 发现三带二，价值: " + trioWithTwo.size());
        }
        
        // 3. 连对
        List<CardObj> consecutivePair = findSmallestConsecutivePair(handCards);
        if (!consecutivePair.isEmpty() && consecutivePair.size() > bestScore) {
            bestCombo = consecutivePair;
            bestScore = consecutivePair.size();
            System.out.println("[残局评估] 发现连对，价值: " + consecutivePair.size());
        }
        
        // 4. 顺子
        List<CardObj> straight = findSmallestStraight(handCards);
        if (!straight.isEmpty() && straight.size() > bestScore) {
            bestCombo = straight;
            bestScore = straight.size();
            System.out.println("[残局评估] 发现顺子，价值: " + straight.size());
        }
        
        // 5. 三张
        List<CardObj> trio = findSmallestTrio(handCards);
        if (!trio.isEmpty() && trio.size() > bestScore) {
            bestCombo = trio;
            bestScore = trio.size();
            System.out.println("[残局评估] 发现三张，价值: " + trio.size());
        }
        
        // 6. 对子
        List<CardObj> pair = findSmallestPair(handCards);
        if (!pair.isEmpty() && pair.size() > bestScore) {
            bestCombo = pair;
            bestScore = pair.size();
            System.out.println("[残局评估] 发现对子，价值: " + pair.size());
        }
        
        // 7. 四带二（仅在完全没有其他组合时考虑）
        List<CardObj> fourWithTwo = findSmallestFourWithTwo(handCards);
        if (!fourWithTwo.isEmpty() && bestScore == 0) {  // 仅在无其他组合时才考虑
            System.out.println("[残局评估] 无其他组合牌型，考虑使用四带二");
            return fourWithTwo;
        }
        
        // 8. 炸弹（仅在完全没有其他组合时考虑）
        List<CardObj> bomb = findSmallestBomb(handCards);
        if (!bomb.isEmpty() && bestScore == 0) {  // 仅在无其他组合时才考虑
            System.out.println("[残局评估] 无其他组合牌型，考虑使用炸弹");
            return bomb;
        }
        
        if (bestScore > 0) {
            System.out.println("[残局决策] 选择最佳组合: " + bestCombo.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        } else {
            System.out.println("[残局决策] 无可用组合牌型");
        }
        
        return bestCombo;
    }
    
    /** 兜底决策 */
    private static ITArray fallbackDecision(List<CardObj> handCards) {
        System.out.println("[兜底策略] 无合适组合，智能选择最小损失");
        
        List<CardObj> pair = findSmallestPair(handCards);
        if (!pair.isEmpty()) {
            System.out.println("[兜底] 出最小对子: " + pair.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.toList()));
            return CardUtil.toTArray(pair);
        }
        
        CardObj minCard = CardUtil.findMinSingleCard(handCards);
        if (minCard != null) {
            System.out.println("[兜底] 出最小单牌: " + getCardName(minCard.cardMod));
            return CardUtil.toTArray1(minCard);
        }
        
        System.out.println("[警告] 无法找到任何可出牌型");
        return new TArray();
    }
    
    // ====================== 新增评估函数 ======================
    
    /** 计算牌力平衡度 */
    private static double calculateBalanceScore(HandAnalysis analysis) {
        double score = 0.0;
        
        // 小牌比例贡献
        double smallRatio = (double)(analysis.lowCards + analysis.mediumCards) / analysis.totalCards;
        score += Math.min(smallRatio * 0.5, 0.4);
        
        // 大牌不过多
        double bigRatio = (double)analysis.bigCards / analysis.totalCards;
        if (bigRatio <= 0.3) {
            score += 0.3;
        } else if (bigRatio <= 0.5) {
            score += 0.2;
        }
        
        // 中等牌适中
        double mediumRatio = (double)analysis.mediumCards / analysis.totalCards;
        if (mediumRatio >= 0.3 && mediumRatio <= 0.6) {
            score += 0.3;
        }
        
        return Math.min(score, 1.0);
    }
    
    /** 计算出牌流畅度 */
    private static double calculateProgressionScore(HandAnalysis analysis) {
        double score = 0.0;
        
        // 小牌充足
        double smallRatio = (double)(analysis.lowCards + analysis.mediumCards) / analysis.totalCards;
        score += Math.min(smallRatio * 0.6, 0.5);
        
        // 连续结构加分
        if (analysis.hasContinuousStructure) score += 0.3;
        
        // 组合牌型丰富
        int comboTypes = (analysis.pairCount > 0 ? 1 : 0) + 
                        (analysis.trioCount > 0 ? 1 : 0) + 
                        (analysis.straightCount > 0 ? 1 : 0);
        score += Math.min(comboTypes * 0.2, 0.4);
        
        return Math.min(score, 1.0);
    }
    
    /** 生成出牌优先级指导 */
    private static List<CardPriority> generatePriorityGuidance(HandAnalysis analysis) {
        List<CardPriority> guidance = new ArrayList<>();
        
        // 根据大牌比例制定策略
        if (analysis.bigCardRatio > 0.4) {
            // 大牌过多，建议保留
            guidance.add(new CardPriority("小牌组合", 1, "大牌过多需先清理小牌", true));
            guidance.add(new CardPriority("中等单牌", 2, "保持出牌流畅性", true));
            guidance.add(new CardPriority("大牌单张", 4, "关键时刻使用", true));
            guidance.add(new CardPriority("大牌组合", 5, "最后阶段使用", true));
        } else if (analysis.balanceScore > 0.6) {
            // 平衡状态
            guidance.add(new CardPriority("最优组合", 1, "按牌力自然出牌", false));
            guidance.add(new CardPriority("连续结构", 2, "发挥连牌优势", false));
        } else {
            // 需要调整
            guidance.add(new CardPriority("改善手牌", 1, "优先调整不利牌型", false));
            guidance.add(new CardPriority("建立优势", 2, "创造更好的出牌机会", false));
        }
        
        return guidance;
    }
    
    // ====================== 评估函数 ======================
    
    private static double calculateComboQuality(HandAnalysis analysis) {
        double quality = 0.0;
        if (analysis.maxStraightLength >= 8) quality += 0.4;
        else if (analysis.maxStraightLength >= 6) quality += 0.3;
        else if (analysis.maxStraightLength >= 5) quality += 0.2;
        
        if (analysis.maxConsecutivePairs >= 4) quality += 0.3;
        else if (analysis.maxConsecutivePairs >= 3) quality += 0.2;
        else if (analysis.maxConsecutivePairs >= 2) quality += 0.1;
        
        quality += Math.min(analysis.airplaneCount * 0.2, 0.3);
        quality += Math.min(analysis.bombCount * 0.25, 0.5);
        
        return Math.min(quality, 1.0);
    }
    
    private static double calculateFlexibilityScore(HandAnalysis analysis) {
        double flexibility = 0.0;
        
        int comboTypes = (analysis.pairCount > 0 ? 1 : 0) + 
                        (analysis.trioCount > 0 ? 1 : 0) + 
                        (analysis.straightCount > 0 ? 1 : 0) +
                        (analysis.consecutivePairCount > 0 ? 1 : 0) +
                        (analysis.airplaneCount > 0 ? 1 : 0);
        flexibility += Math.min(comboTypes * 0.2, 0.8);
        
        double mediumRatio = (double) analysis.mediumCards / analysis.totalCards;
        flexibility += mediumRatio * 0.4;
        
        if (analysis.hasContinuousStructure) flexibility += 0.3;
        
        return Math.min(flexibility, 1.0);
    }
    
    private static double calculateControlScore(HandAnalysis analysis) {
        double control = 0.0;
        
        double highRatio = (double) analysis.highCards / analysis.totalCards;
        control += highRatio * 0.4;
        
        control += Math.min(analysis.bombCount * 0.3, 0.6);
        control += Math.min(analysis.trioCount * 0.15, 0.3);
        
        if (analysis.hasContinuousStructure) control += 0.2;
        
        return Math.min(control, 1.0);
    }
    
    private static double calculateRiskScore(HandAnalysis analysis) {
        double score = 0.0;
        
        double singleRatio = (double) analysis.singleCount / analysis.totalCards;
        score += singleRatio * 0.4;
        
        double highCardRisk = (double) analysis.highCards / analysis.totalCards;
        if (analysis.pairCount + analysis.trioCount + analysis.bombCount == 0) {
            score += highCardRisk * 0.3;
        }
        
        int comboTypes = (analysis.pairCount > 0 ? 1 : 0) + 
                        (analysis.trioCount > 0 ? 1 : 0) + 
                        (analysis.straightCount > 0 ? 1 : 0);
        if (comboTypes <= 1) score += 0.3;
        
        return Math.min(score, 1.0);
    }
    
    private static double calculateVulnerabilityScore(HandAnalysis analysis) {
        double vulnerability = 0.0;
        
        double highAloneRatio = (double) analysis.highCards / analysis.totalCards;
        if (analysis.pairCount + analysis.trioCount == 0) {
            vulnerability += highAloneRatio * 0.5;
        }
        
        double singleRatio = (double) analysis.singleCount / analysis.totalCards;
        vulnerability += singleRatio * 0.4;
        
        if (analysis.bombCount == 0 && analysis.trioCount == 0) {
            vulnerability += 0.3;
        }
        
        return Math.min(vulnerability, 1.0);
    }
    
    private static StrategyTendency determineStrategyTendency(GameSituation situation) {
        if (situation.pressureLevel > 0.7) {
            if (situation.opportunityLevel > 0.6) {
                return StrategyTendency.OPPORTUNISTIC;
            } else {
                return StrategyTendency.AGGRESSIVE;
            }
        } else if (situation.pressureLevel < 0.3) {
            return StrategyTendency.CONSERVATIVE;
        } else {
            return StrategyTendency.BALANCED;
        }
    }
    
    private static String recommendAdvancedStrategy(HandAnalysis analysis) {
        int comboTypes = (analysis.pairCount > 0 ? 1 : 0) + 
                        (analysis.trioCount > 0 ? 1 : 0) + 
                        (analysis.straightCount > 0 ? 1 : 0) +
                        (analysis.consecutivePairCount > 0 ? 1 : 0) +
                        (analysis.airplaneCount > 0 ? 1 : 0) +
                        (analysis.bombCount > 0 ? 1 : 0);
        
        double lowRatio = (double) analysis.lowCards / analysis.totalCards;
        double highRatio = (double) analysis.highCards / analysis.totalCards;
        
        double straightWeight = analysis.maxStraightLength >= 6 ? 0.9 : 
                              analysis.maxStraightLength >= 5 ? 0.7 : 0.3;
        double comboWeight = Math.min(comboTypes * 0.2, 0.8);
        double controlWeight = analysis.controlScore;
        
        if (straightWeight >= 0.8 && analysis.straightCount > 0) {
            return "顺子主导";
        } else if (comboWeight >= 0.6 && comboTypes >= 3) {
            return "复合牌型";
        } else if (analysis.pairCount >= 3 && analysis.flexibilityScore > 0.6) {
            return "对子推进";
        } else if (analysis.trioCount >= 2 && controlWeight > 0.5) {
            return "三张控制";
        } else if (lowRatio > 0.7) {
            return "快速清理";
        } else if (highRatio > 0.6 && analysis.bombCount > 0) {
            return "蓄力待发";
        } else {
            return "灵活应变";
        }
    }
    
    private static List<String> generateAlternativeStrategies(HandAnalysis analysis) {
        List<String> alternatives = new ArrayList<>();
        
        if (analysis.straightCount > 0) alternatives.add("顺子流");
        if (analysis.pairCount > 0) alternatives.add("对子流");
        if (analysis.trioCount > 0) alternatives.add("三张流");
        if (analysis.bombCount > 0) alternatives.add("炸弹流");
        if (analysis.lowCards > analysis.totalCards * 0.6) alternatives.add("清小牌");
        if (analysis.highCards > analysis.totalCards * 0.5) alternatives.add("控大牌");
        
        return alternatives;
    }

    // ====================== 打印分析结果 ======================
    
    private static void printHandAnalysis(HandAnalysis analysis) {
        System.out.println("\n========== 手牌深度分析报告 ==========");
        System.out.println("📊 基础构成: " + analysis.toString());
        System.out.println("🔗 连续结构: 最长顺子" + analysis.maxStraightLength + "张, 最大连对" + analysis.maxConsecutivePairs + "对");
        System.out.println("📈 质量评估: 组合质量" + String.format("%.2f", analysis.comboQualityScore) + 
                          ", 灵活性" + String.format("%.2f", analysis.flexibilityScore) + 
                          ", 控制力" + String.format("%.2f", analysis.controlScore));
        System.out.println("⚠️  风险评估: 风险评分" + String.format("%.2f", analysis.riskScore) + 
                          ", 脆弱性" + String.format("%.2f", analysis.vulnerabilityScore));
        System.out.println("🎯 AI建议: " + analysis.recommendedStrategy);
        if (analysis.alternativeStrategies != null && !analysis.alternativeStrategies.isEmpty()) {
            System.out.println("🔄 备选策略: " + String.join(", ", analysis.alternativeStrategies));
        }
        System.out.println("=====================================");
    }
    
    private static void printSituationAnalysis(GameSituation situation) {
        System.out.println("\n========== 游戏局势分析报告 ==========");
        System.out.println("🌍 局势类型: " + situation.situationType.getDescription());
        System.out.println("💪 压力等级: " + String.format("%.2f", situation.pressureLevel) + "/1.0");
        System.out.println("⭐ 机会等级: " + String.format("%.2f", situation.opportunityLevel) + "/1.0");
        System.out.println("🧭 策略倾向: " + situation.tendency.getDescription());
        System.out.println("👥 对手信息: " + situation.opponentCount + "个对手, 剩余牌数" + situation.opponentRemainCards);
        System.out.println("=====================================");
    }

    // ====================== 核心查找方法 ======================
    
    private static List<CardObj> findBestQualityCombo(List<CardObj> handCards, HandAnalysis analysis) {
        List<CardObj> result;
        
        result = findSmallestBomb(handCards);
        if (!result.isEmpty()) return result;
        
        result = findSmallestAirplaneWithCards(handCards);
        if (!result.isEmpty()) return result;
        
        result = findSmallestFourWithTwo(handCards);
        if (!result.isEmpty()) return result;
        
        result = findSmallestTrioWithTwo(handCards);
        if (!result.isEmpty()) return result;
        
        result = findSmallestStraight(handCards);
        if (!result.isEmpty()) return result;
        
        result = findSmallestConsecutivePair(handCards);
        if (!result.isEmpty()) return result;
        
        return new ArrayList<>();
    }
    
    private static List<CardObj> findLargestStraight(List<CardObj> handCards) {
        List<List<CardObj>> allStraights = findAllStraights(handCards, 5);
        return allStraights.stream()
                .max(Comparator.comparingInt(s -> s.stream().mapToInt(c -> c.cardMod).sum()))
                .orElse(new ArrayList<>());
    }
    
    private static List<CardObj> findLargePair(List<CardObj> handCards, int minValue) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        return groups.entrySet().stream()
                .filter(e -> e.getKey() >= minValue && e.getValue().size() >= 2)
                .sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
                .map(e -> e.getValue().subList(0, 2))
                .findFirst()
                .orElse(new ArrayList<>());
    }
    
    private static List<CardObj> findSmallComboConservative(List<CardObj> handCards) {
        for (int len = 6; len >= 5; len--) {
            List<List<CardObj>> straights = findAllStraights(handCards, len);
            for (List<CardObj> straight : straights) {
                if (straight.stream().allMatch(c -> c.cardMod <= CARD_8)) {
                    return straight;
                }
            }
        }
        
        List<List<CardObj>> pairs = findAllConsecutivePairs(handCards, 2);
        for (List<CardObj> pair : pairs) {
            if (pair.stream().allMatch(c -> c.cardMod <= CARD_8)) {
                return pair;
            }
        }
        
        return new ArrayList<>();
    }
    
    private static List<CardObj> findOpportunisticBest(List<CardObj> handCards, HandAnalysis analysis, GameSituation situation) {
        if (situation.pressureLevel > 0.6) {
            List<CardObj> bomb = findSmallestBomb(handCards);
            if (!bomb.isEmpty()) return bomb;
            
            List<CardObj> trio = findSmallestTrioWithTwo(handCards);
            if (!trio.isEmpty()) return trio;
        }
        
        if (situation.opportunityLevel > 0.6) {
            return findBestQualityCombo(handCards, analysis);
        }
        
        return findMostFlexibleMove(handCards);
    }

    private static List<CardObj> findMostFlexibleMove(List<CardObj> handCards) {
        List<CardObj> pair = findSmallestPair(handCards);
        if (!pair.isEmpty() && pair.get(0).cardMod <= CARD_J) {
            return pair;
        }
        
        List<CardObj> straight = findSmallestStraight(handCards);
        if (!straight.isEmpty()) {
            return straight;
        }
        
        CardObj smallCard = findSmallNonBigCard(handCards);
        if (smallCard != null) {
            return Collections.singletonList(smallCard);
        }
        
        return new ArrayList<>();
    }

    // ====================== 基础工具方法 ======================
    
    private static boolean isFirstTurn(ITObject card_list) {
        return card_list == null ||
                !card_list.containsKey("card_list") || card_list.getTArray("card_list").size() == 0;
    }

    private static boolean isReacquirePlayTurn(HuNanPaoDeKuai huNanPaoDeKuai, Map<Integer, List<Integer>> seatRemainHistory, ITObject card_list) {
        if (huNanPaoDeKuai == null || card_list == null || seatRemainHistory == null) return false;
        return huNanPaoDeKuai.guangboseat == huNanPaoDeKuai.seat && !isFirstTurn(card_list);
    }

    private static boolean isOpponentEndgame(int currentSeat, Map<Integer, List<Integer>> seatRemainHistory) {
        if (seatRemainHistory == null) return false;
        return seatRemainHistory.entrySet().stream()
                .filter(e -> e.getKey() != currentSeat)
                .anyMatch(e -> !e.getValue().isEmpty() && e.getValue().get(e.getValue().size() - 1) == 1);
    }

    private static ITArray handleOpponentEndgameResponse(List<CardObj> handCards, int type, int minCard, List<CardObj> opponentCards) {
        System.out.println("[残局响应] 分析是否可以用组合牌压制");
        
        // 1. 首先尝试用组合牌型压制
        List<CardObj> comboResponse = findEndgameComboResponse(handCards, type, minCard);
        if (!comboResponse.isEmpty()) {
            System.out.println("[残局策略] 使用组合牌型压制: " + comboResponse.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
            return CardUtil.toTArray(comboResponse);
        }
        
        // 2. 如果没有组合牌型，才考虑单牌压制
        if (type == TYPE_SINGLE) {
            CardObj maxCard = CardUtil.findMaxSingleCard(handCards);
            if (maxCard != null && maxCard.cardMod > minCard) {
                System.out.println("[残局策略] 无组合牌型，出最大单牌压制: " + getCardName(maxCard.cardMod));
                return CardUtil.toTArray1(maxCard);
            }
        }
        
        // 3. 其他牌型按正常逻辑处理
        List<CardObj> response = findMatchingResponse(handCards, type, minCard, 0, opponentCards);
        if (!response.isEmpty()) {
            return CardUtil.toTArray(response);
        }

        // 4. 最后使用炸弹
        List<CardObj> bomb = findSmallestBomb(handCards);
        if (!bomb.isEmpty()) {
            System.out.println("[残局策略] 使用炸弹");
            return CardUtil.toTArray(bomb);
        }

        // 5. 单牌兜底
        if (type == TYPE_SINGLE) {
            CardObj maxCard = CardUtil.findMaxSingleCard(handCards);
            if (maxCard != null) {
                System.out.println("[残局策略] 出最大单牌(最终兜底): " + getCardName(maxCard.cardMod));
                return CardUtil.toTArray1(maxCard);
            }
        }

        return new TArray();
    }
    
    /** 对手剩余两张牌的试探响应策略 */
    private static ITArray handleOpponentTwoCardsResponse(List<CardObj> handCards, int type, int minCard, List<CardObj> opponentCards) {
        System.out.println("[试探策略] 分析是否需要试探对手手牌构成");
        
        // 检查机器人是否持有大单牌（Q及以上）
        boolean hasBigSingleCards = hasBigSingleCards(handCards);
        System.out.println("[试探策略] 是否持有大单牌(Q及以上): " + hasBigSingleCards);
        
        // 如果机器人准备出小对子（小于J），则采用试探策略
        if (type == TYPE_PAIR && minCard < CARD_J) {
            List<CardObj> smallPair = findSmallPair(handCards, CARD_J - 1);
            if (!smallPair.isEmpty() && hasBigSingleCards) {
                System.out.println("[试探策略] 检测到小对子响应且持有大单牌，启动试探模式");
                return handleProbeStrategy(handCards, smallPair);
            }
        }
        
        // 其他情况按正常逻辑处理
        List<CardObj> response = findMatchingResponse(handCards, type, minCard, 0, opponentCards);
        if (!response.isEmpty()) {
            return CardUtil.toTArray(response);
        }
        
        // 最后使用炸弹
        List<CardObj> bomb = findSmallestBomb(handCards);
        if (!bomb.isEmpty()) {
            System.out.println("[试探策略] 使用炸弹");
            return CardUtil.toTArray(bomb);
        }
        
        return new TArray();
    }
    
    /** 检查是否持有大单牌（Q及以上）*/
    private static boolean hasBigSingleCards(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 查找Q及以上且是单牌的牌
        for (Map.Entry<Integer, List<CardObj>> entry : groups.entrySet()) {
            int value = entry.getKey();
            List<CardObj> cards = entry.getValue();
            
            if (value >= CARD_Q && cards.size() == 1) {
                return true;
            }
        }
        return false;
    }
    
    /** 试探策略核心逻辑 */
    private static ITArray handleProbeStrategy(List<CardObj> handCards, List<CardObj> smallPair) {
        System.out.println("[试探策略] 执行试探性出牌策略");
        
        // 方案1：先出一张中等单牌进行试探（8-K范围内）
        CardObj probeCard = findProbeSingleCard(handCards);
        if (probeCard != null) {
            System.out.println("[试探策略] 出试探单牌: " + getCardName(probeCard.cardMod) + "，观察对手反应");
            return CardUtil.toTArray1(probeCard);
        }
        
        // 方案2：如果没有合适的试探单牌，则直接出小对子（风险较高）
        System.out.println("[试探策略] 无合适试探单牌，直接出小对子: " + 
            smallPair.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        return CardUtil.toTArray(smallPair);
    }
    
    /** 寻找用于试探的单牌（8-K范围）*/
    private static CardObj findProbeSingleCard(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 寻找8-K范围内的单牌
        List<CardObj> candidates = new ArrayList<>();
        
        for (Map.Entry<Integer, List<CardObj>> entry : groups.entrySet()) {
            int value = entry.getKey();
            List<CardObj> cards = entry.getValue();
            
            // 必须是单牌且在8-K范围内
            if (cards.size() == 1 && value >= CARD_8 && value <= CARD_K) {
                candidates.add(cards.get(0));
            }
        }
        
        if (!candidates.isEmpty()) {
            // 优先选择较小的试探牌
            candidates.sort(Comparator.comparingInt(CardObj::getCardMod));
            CardObj selected = candidates.get(0);
            System.out.println("[试探牌选择] 在" + candidates.size() + "个候选手牌中选择: " + getCardName(selected.cardMod));
            return selected;
        }
        
        System.out.println("[试探牌选择] 未找到8-K范围内的单牌");
        return null;
    }
    
    /** 残局组合牌压制 */
    private static List<CardObj> findEndgameComboResponse(List<CardObj> handCards, int targetType, int minCard) {
        System.out.println("[残局压制] 寻找可以压制的组合牌型");
        
        // 只有在对手出单牌时才考虑组合牌压制
        if (targetType != TYPE_SINGLE) {
            return new ArrayList<>();
        }
        
        List<CardObj> bestCombo = new ArrayList<>();
        int bestScore = 0;
        
        // 评估各种可以压制单牌的组合牌型
        
        // 1. 炸弹（无条件压制）
        List<CardObj> bomb = findSmallestBomb(handCards);
        if (!bomb.isEmpty()) {
            System.out.println("[残局压制] 发现炸弹，直接压制");
            return bomb;
        }
        
        // 2. 对子（压制单牌）
        List<CardObj> pair = findSmallestPair(handCards);
        if (!pair.isEmpty() && pair.get(0).cardMod > minCard) {
            if (2 > bestScore) {
                bestCombo = pair;
                bestScore = 2;
                System.out.println("[残局压制] 发现可压制对子");
            }
        }
        
        // 3. 三张（压制单牌）
        List<CardObj> trio = findSmallestTrio(handCards);
        if (!trio.isEmpty() && trio.get(0).cardMod > minCard) {
            if (3 > bestScore) {
                bestCombo = trio;
                bestScore = 3;
                System.out.println("[残局压制] 发现可压制三张");
            }
        }
        
        // 4. 连对（压制单牌）
        List<CardObj> consecutivePair = findSmallestConsecutivePair(handCards);
        if (!consecutivePair.isEmpty() && consecutivePair.get(0).cardMod > minCard) {
            if (consecutivePair.size() > bestScore) {
                bestCombo = consecutivePair;
                bestScore = consecutivePair.size();
                System.out.println("[残局压制] 发现可压制连对");
            }
        }
        
        // 5. 顺子（压制单牌）
        List<CardObj> straight = findSmallestStraight(handCards);
        if (!straight.isEmpty() && straight.get(0).cardMod > minCard) {
            if (straight.size() > bestScore) {
                bestCombo = straight;
                bestScore = straight.size();
                System.out.println("[残局压制] 发现可压制顺子");
            }
        }
        
        return bestCombo;
    }

    private static boolean isIllegalTrioWithOne(ITArray cards) {
        if (cards.size() != 4) return false;
        List<CardObj> cardList = CardUtil.toList(cards);
        Map<Integer, Integer> countMap = CardUtil.getCardNumMap(cardList);
        return countMap.containsValue(3) && countMap.containsValue(1);
    }

    private static ITArray reselectLegalCards(List<CardObj> handCards) {
        List<CardObj> pair = findSmallestPair(handCards);
        if (!pair.isEmpty()) {
            return CardUtil.toTArray(pair);
        }
        return CardUtil.toTArray1(CardUtil.findMinSingleCard(handCards));
    }

    private static ITArray emergencyOutCard(List<CardObj> handCards) {
        if (handCards.isEmpty()) return new TArray();
        CardObj minCard = CardUtil.findMinSingleCard(handCards);
        System.out.println("[紧急策略] 出最小合规单牌: " + getCardName(minCard.cardMod));
        return CardUtil.toTArray1(minCard);
    }

    private static List<CardObj> findMatchingResponse(List<CardObj> handCards, int type, int minCard, int len, List<CardObj> opponentCards) {
        System.out.println("[智能响应] 收到出牌请求 - 报告类型:" + getCardTypeName(type) + ", 最小牌:" + getCardName(minCard) + ", 长度:" + len);
        
        // 智能纠错：根据牌数和常见模式推断真实牌型
        System.out.println("[智能响应] 原始报告类型:" + getCardTypeName(type) + ", 牌数:" + len + ", 最小牌:" + getCardName(minCard));
        int correctedType = correctCardTypeByPattern(type, len, minCard);
        if (correctedType != type) {
            System.out.println("[智能纠错] 检测到类型推断可能有误，原始:" + getCardTypeName(type) + " -> 纠正:" + getCardTypeName(correctedType));
            type = correctedType;
        } else {
            System.out.println("[智能纠错] 类型判断一致，无需纠正");
        }
        
        // 直接分析实际牌面构成，这才是真正的智能！
        if (opponentCards != null && !opponentCards.isEmpty()) {
            int actualType = analyzeActualCardType(opponentCards);
            System.out.println("[智能分析] 实际牌面分析结果 - 真实类型:" + getCardTypeName(actualType));
            
            // 优先信任我们自己的分析结果
            if (actualType != type) {
                System.out.println("[智能纠错] 检测到服务器报告类型与实际不符，采用智能分析结果");
                type = actualType;
            }
        } else {
            System.out.println("[智能分析] 无法获取实际出牌信息，依赖模式纠错");
        }

        switch (type) {
            case TYPE_SINGLE:
                return findSingleResponse(handCards, minCard);
            case TYPE_PAIR:
                return findPairResponse(handCards, minCard);
            case TYPE_STRAIGHT:
                return findStraightResponse(handCards, minCard, len);
            case TYPE_CONSECUTIVE_PAIR:
                return findConsecutivePairResponse(handCards, minCard, len);
            case TYPE_TRIO:
                return findTrioResponse(handCards, minCard);
            case TYPE_TRIO_WITH_TWO:
                return findTrioWithTwoResponse(handCards, minCard);
            case TYPE_BOMB:
                return findBombResponse(handCards, minCard);
            case TYPE_AIRPLANE_WITH_CARDS:
                return findAirplaneWithCardsResponse(handCards, minCard, len);
            case TYPE_FOUR_WITH_TWO:
            case TYPE_FOUR_WITH_TWO_PAIR:
                return findFourWithTwoResponse(handCards, minCard);
            default:
                System.out.println("未知/非法牌型: " + type + "，无法响应");
                return new ArrayList<>();
        }
    }

    private static List<CardObj> findSingleResponse(List<CardObj> handCards, int minCard) {
        System.out.println("[单牌响应] 寻找大于" + getCardName(minCard) + "的单牌");
        
        // 首先查找真正的单牌（手中只有一张的牌）
        List<CardObj> trueSingleCards = handCards.stream()
                .filter(c -> CardUtil.getCardNumMap(handCards).get(c.cardMod) == 1) // 确保是单牌
                .filter(c -> c.cardMod > minCard) // 必须大于对手的牌
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        if (!trueSingleCards.isEmpty()) {
            // 有真正的单牌，使用智能选择策略
            CardObj smartChoice = findSmartSingleCard(handCards, minCard);
            if (smartChoice != null) {
                System.out.println("[单牌响应] 智能选择单牌: " + getCardName(smartChoice.cardMod));
                return Collections.singletonList(smartChoice);
            }
            // 兜底选择最小单牌
            CardObj minCardObj = trueSingleCards.get(0);
            System.out.println("[单牌响应] 兜底选择最小单牌: " + getCardName(minCardObj.cardMod));
            return Collections.singletonList(minCardObj);
        }
        
        // 没有真正的单牌，必须拆组合牌
        System.out.println("[单牌响应] 无真正单牌，需要拆组合牌");
        CardObj breakChoice = findBestCardToBreak(handCards, minCard);
        
        if (breakChoice != null) {
            System.out.println("[单牌响应] 拆组合牌选择: " + getCardName(breakChoice.cardMod));
            return Collections.singletonList(breakChoice);
        }
        
        System.out.println("[单牌响应] 无合适单牌可出");
        return new ArrayList<>();
    }

    private static List<CardObj> findPairResponse(List<CardObj> handCards, int minCard) {
        Map<Integer, List<CardObj>> valueGroups = CardUtil.getCardListMap(handCards);
        return valueGroups.entrySet().stream()
                .filter(e -> e.getKey() > minCard && e.getValue().size() >= 2)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 2))
                .findFirst()
                .orElse(new ArrayList<>());
    }

    private static List<CardObj> findStraightResponse(List<CardObj> handCards, int minCard, int len) {
        if (len < MIN_STRAIGHT_LENGTH) return new ArrayList<>();

        List<List<CardObj>> allStraights = findAllStraights(handCards, len);
        return allStraights.stream()
                .filter(s -> s.get(0).cardMod > minCard)
                .sorted(Comparator.comparingInt(s -> s.get(0).cardMod))
                .findFirst()
                .orElse(new ArrayList<>());
    }

    private static List<CardObj> findConsecutivePairResponse(List<CardObj> handCards, int minCard, int len) {
        // 修正：len表示连对的数量，不是总牌数
        // 但是要考虑服务器可能传递的是总牌数的情况
        int pairCount;
        
        // 智能推断连对数量
        if (len == 0) {
            // 服务器传0，说明是2连对（最常见的连对）
            pairCount = 2;
            System.out.println("[连对响应] 服务器传len=0，推断为2连对");
        } else if (len >= 4 && len % 2 == 0) {
            // 如果len是偶数且>=4，可能是总牌数，需要转换为连对数
            pairCount = len / 2;  // 4张牌=2连对，6张牌=3连对
            System.out.println("[连对响应] 检测到总牌数" + len + "，转换为" + pairCount + "连对");
        } else if (len >= MIN_CONSECUTIVE_PAIR_COUNT && len <= 6) {
            // 标准的连对数（2-6连对）
            pairCount = len;
            System.out.println("[连对响应] 直接使用连对数" + len);
        } else {
            // 默认推断为2连对
            pairCount = 2;
            System.out.println("[连对响应] 无法识别len=" + len + "，默认推断为2连对");
        }
        
        System.out.println("[连对响应] 寻找" + pairCount + "连对(共" + (pairCount*2) + "张牌)，最小起始牌:" + getCardName(minCard));
        
        // 手牌分析
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        System.out.println("[连对响应] 手牌中的对子情况:");
        groups.forEach((k, v) -> {
            if (v.size() >= 2) {
                System.out.println("  " + getCardName(k) + ": " + v.size() + "张");
            }
        });

        if (pairCount < MIN_CONSECUTIVE_PAIR_COUNT) {
            System.out.println("对手连对数" + pairCount + "<" + MIN_CONSECUTIVE_PAIR_COUNT + "，不符合规则，无法响应");
            return new ArrayList<>();
        }

        List<List<CardObj>> allConsecutivePairs = findAllConsecutivePairs(handCards, pairCount);
        
        System.out.println("[连对响应] 找到" + allConsecutivePairs.size() + "个符合条件的连对");
        for (int i = 0; i < allConsecutivePairs.size(); i++) {
            List<CardObj> pair = allConsecutivePairs.get(i);
            System.out.println("  连对" + (i+1) + ": " + pair.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        }

        List<List<CardObj>> validPairs = allConsecutivePairs.stream()
                .filter(p -> p.get(0).cardMod > minCard)
                .sorted(Comparator.comparingInt(p -> p.get(0).cardMod))
                .collect(Collectors.toList());
                
        if (!validPairs.isEmpty()) {
            List<CardObj> chosenPair = validPairs.get(0);
            System.out.println("[连对响应] 选择出牌:" + chosenPair.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            return chosenPair;
        }
        
        System.out.println("[连对响应] 无合适连对可出");
        return new ArrayList<>();
    }

    private static List<CardObj> findTrioResponse(List<CardObj> handCards, int minCard) {
        Map<Integer, List<CardObj>> valueGroups = CardUtil.getCardListMap(handCards);
        
        List<CardObj> result = valueGroups.entrySet().stream()
                .filter(e -> e.getKey() > minCard && e.getValue().size() >= 3)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 3))
                .findFirst()
                .orElse(new ArrayList<>());
                
        return result;
    }

    private static List<CardObj> findTrioWithTwoResponse(List<CardObj> handCards, int minCard) {
        System.out.println("[三带二响应] 寻找能压制" + getCardName(minCard) + "的三带二");
        
        Map<Integer, List<CardObj>> valueGroups = CardUtil.getCardListMap(handCards);
        
        // 调试信息
        System.out.println("[三带二响应] 手牌分组情况:");
        valueGroups.forEach((k, v) -> {
            System.out.println("  " + getCardName(k) + ": " + v.size() + "张");
        });
        
        // 寻找三张
        Optional<Map.Entry<Integer, List<CardObj>>> trioEntry = valueGroups.entrySet().stream()
                .filter(e -> e.getKey() > minCard && e.getValue().size() >= 3)
                .sorted(Map.Entry.comparingByKey())
                .findFirst();

        if (!trioEntry.isPresent()) {
            System.out.println("[三带二响应] 未找到大于" + getCardName(minCard) + "的三张");
            return new ArrayList<>();
        }
        
        System.out.println("[三带二响应] 找到三张: " + getCardName(trioEntry.get().getKey()));

        // 智能选择携带的两张牌 - 优先带走单牌
        List<CardObj> carryCards = selectOptimalCarryCards(handCards, trioEntry.get().getKey());
        
        if (carryCards.size() < 2) {
            System.out.println("[三带二响应] 未找到足够的携带牌");
            return new ArrayList<>();
        }
        
        System.out.println("[三带二响应] 选择携带: " + carryCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));

        List<CardObj> result = new ArrayList<>(trioEntry.get().getValue().subList(0, 3));
        result.addAll(carryCards.subList(0, 2));
        
        System.out.println("[三带二响应] 最终出牌: " + result.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        return result;
    }
    
    /**
     * 智能选择三带二的携带牌
     * 策略：优先带走单牌，优化手牌结构
     */
    private static List<CardObj> selectOptimalCarryCards(List<CardObj> handCards, int trioValue) {
        System.out.println("[智能携带] 分析携带牌选择策略");
        
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        List<CardObj> carryCandidates = new ArrayList<>();
        
        // 获取可用于携带的牌（排除三张牌）
        List<CardObj> availableCards = handCards.stream()
                .filter(c -> c.cardMod != trioValue)
                .collect(Collectors.toList());
        
        // 1. 优先选择不会破坏组合结构的安全单牌
        List<CardObj> safeSingleCards = availableCards.stream()
                .filter(c -> groups.get(c.cardMod).size() == 1)  // 只要单牌
                .filter(c -> !wouldBreakComboStructure(c, availableCards)) // 避免破坏组合
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        System.out.println("[智能携带] 安全单牌: " + safeSingleCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        
        if (safeSingleCards.size() >= 2) {
            // 选择两张安全单牌带走
            carryCandidates.addAll(safeSingleCards.subList(0, 2));
            System.out.println("[智能携带] 选择带走2张安全单牌，保护组合结构");
            return carryCandidates;
        }
        
        // 2. 考虑特殊情况：如果剩余牌型结构良好，可以考虑带2
        List<CardObj> twoCards = availableCards.stream()
                .filter(c -> c.cardMod == CARD_2)
                .collect(Collectors.toList());
        
        if (!twoCards.isEmpty() && wouldAllowCarryingTwoSpecial(availableCards)) {
            System.out.println("[智能携带] 特殊情况允许带2");
            carryCandidates.addAll(twoCards);
            // 补充另一张安全牌
            List<CardObj> otherSafeCards = availableCards.stream()
                    .filter(c -> c.cardMod != CARD_2)
                    .filter(c -> !wouldBreakComboStructure(c, availableCards))
                    .sorted(Comparator.comparingInt(CardObj::getCardMod))
                    .collect(Collectors.toList());
            
            if (!otherSafeCards.isEmpty()) {
                carryCandidates.add(otherSafeCards.get(0));
                System.out.println("[智能携带] 带2方案成功: " + 
                    carryCandidates.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
                return carryCandidates;
            }
        }
        
        // 3. 最后的备选方案：选择最小的牌
        List<CardObj> otherCards = availableCards.stream()
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        if (otherCards.size() >= 2) {
            carryCandidates.addAll(otherCards.subList(0, 2));
            System.out.println("[智能携带] 备选方案-选择带走2张最小牌");
            return carryCandidates;
        }
        
        System.out.println("[智能携带] 无可选携带牌");
        return new ArrayList<>();
    }
    
    /** 特殊情况判断是否允许带2 */
    private static boolean wouldAllowCarryingTwoSpecial(List<CardObj> availableCards) {
        // 移除2后分析剩余牌的组合潜力
        List<CardObj> withoutTwos = availableCards.stream()
                .filter(card -> card.cardMod != CARD_2)
                .collect(Collectors.toList());
        
        ComboPotential potential = analyzeComboPotential(withoutTwos);
        
        // 如果移除2后仍有良好的组合结构，则允许带2
        boolean hasGoodStructure = potential.hasGoodStructure();
        
        System.out.println("[带2特殊判断] 移除2后剩余牌潜力: " + potential + ", 结构良好: " + hasGoodStructure);
        
        return hasGoodStructure;
    }

    private static List<CardObj> findBombResponse(List<CardObj> handCards, int minCard) {
        System.out.println("[炸弹响应] 寻找大于" + getCardName(minCard) + "的炸弹");
        
        Map<Integer, List<CardObj>> valueGroups = CardUtil.getCardListMap(handCards);
        
        // 调试信息
        System.out.println("[炸弹响应] 手牌中的炸弹候选:");
        valueGroups.forEach((k, v) -> {
            if (v.size() >= 4) {
                System.out.println("  " + getCardName(k) + ": " + v.size() + "张");
            }
        });
        
        List<CardObj> result = valueGroups.entrySet().stream()
                .filter(e -> e.getKey() > minCard && e.getValue().size() >= 4)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 4))
                .findFirst()
                .orElse(new ArrayList<>());
                
        if (!result.isEmpty()) {
            System.out.println("[炸弹响应] 找到炸弹: " + result.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        } else {
            System.out.println("[炸弹响应] 未找到可压制的炸弹");
        }
        
        return result;
    }

    /**
     * 智能响应飞机带牌
     * 支持多种带牌方式的飞机，根据实际牌型灵活应对
     */
    private static List<CardObj> findAirplaneWithCardsResponse(List<CardObj> handCards, int minCard, int len) {
        System.out.println("[飞机响应] 寻找能压制" + getCardName(minCard) + "的飞机，总牌数:" + len);
        
        // 计算需要的三张组数
        int trioCount = calculateRequiredTrioCount(len);
        if (trioCount < MIN_AIRPLANE_TRIO_COUNT) {
            System.out.println("[飞机响应] 三张组数" + trioCount + "小于最小要求" + MIN_AIRPLANE_TRIO_COUNT);
            return new ArrayList<>();
        }
        
        System.out.println("[飞机响应] 需要" + trioCount + "组连续三张");
        
        // 查找所有可能的飞机
        List<List<CardObj>> allAirplanes = findAllAirplanesWithCards(handCards, trioCount);
        System.out.println("[飞机响应] 找到" + allAirplanes.size() + "个可行的飞机");
        
        // 筛选能压制的飞机
        List<List<CardObj>> validAirplanes = allAirplanes.stream()
                .filter(airplane -> {
                    // 提取三张部分的最小值
                    Map<Integer, Long> countMap = airplane.stream()
                            .collect(Collectors.groupingBy(CardObj::getCardMod, Collectors.counting()));
                    int minTrioValue = countMap.entrySet().stream()
                            .filter(e -> e.getValue() >= 3)
                            .mapToInt(Map.Entry::getKey)
                            .min()
                            .orElse(0);
                    return minTrioValue > minCard;
                })
                .sorted((a1, a2) -> {
                    // 优先选择三张部分较小的飞机（更节约）
                    Map<Integer, Long> countMap1 = a1.stream()
                            .collect(Collectors.groupingBy(CardObj::getCardMod, Collectors.counting()));
                    Map<Integer, Long> countMap2 = a2.stream()
                            .collect(Collectors.groupingBy(CardObj::getCardMod, Collectors.counting()));
                    
                    int min1 = countMap1.entrySet().stream()
                            .filter(e -> e.getValue() >= 3)
                            .mapToInt(Map.Entry::getKey)
                            .min()
                            .orElse(0);
                    int min2 = countMap2.entrySet().stream()
                            .filter(e -> e.getValue() >= 3)
                            .mapToInt(Map.Entry::getKey)
                            .min()
                            .orElse(0);
                    
                    return Integer.compare(min1, min2);
                })
                .collect(Collectors.toList());
        
        if (!validAirplanes.isEmpty()) {
            List<CardObj> chosenAirplane = validAirplanes.get(0);
            System.out.println("[飞机响应] 选择出牌: " + 
                chosenAirplane.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            return chosenAirplane;
        }
        
        System.out.println("[飞机响应] 无合适飞机可出");
        return new ArrayList<>();
    }
    
    /**
     * 根据总牌数计算需要的三张组数
     * 跑得快规则：飞机带牌 = 三张组数 × (3 + 带牌系数)
     * 带牌系数通常为2（带两对）或1（带两张单牌）
     */
    private static int calculateRequiredTrioCount(int totalLen) {
        // 常见的飞机带牌格式：
        // 2连飞机带2对：2×(3+2) = 10张
        // 2连飞机带2单：2×(3+1) = 8张  
        // 3连飞机带3对：3×(3+2) = 15张
        // 3连飞机带3单：3×(3+1) = 12张
        
        if (totalLen == 10) return 2; // 2连飞机带2对
        if (totalLen == 8) return 2;  // 2连飞机带2单
        if (totalLen == 15) return 3; // 3连飞机带3对
        if (totalLen == 12) return 3; // 3连飞机带3单
        if (totalLen == 20) return 4; // 4连飞机
        
        // 通用计算：假设带牌系数为2（带对子）
        if (totalLen % 5 == 0) {
            return totalLen / 5; // 3+2格式
        }
        
        // 假设带牌系数为1（带单牌）
        if (totalLen % 4 == 0) {
            return totalLen / 4; // 3+1格式
        }
        
        return 0; // 无法识别的格式
    }

    private static List<CardObj> findFourWithTwoResponse(List<CardObj> handCards, int minCard) {
        Map<Integer, List<CardObj>> valueGroups = CardUtil.getCardListMap(handCards);
        Optional<Map.Entry<Integer, List<CardObj>>> fourEntry = valueGroups.entrySet().stream()
                .filter(e -> e.getKey() > minCard && e.getValue().size() >= 4)
                .sorted(Map.Entry.comparingByKey())
                .findFirst();

        if (!fourEntry.isPresent()) return new ArrayList<>();

        List<CardObj> four = fourEntry.get().getValue().subList(0, 4);
        List<CardObj> carryCards = findTwoMinCardsExcept(handCards, fourEntry.get().getKey());
        if (carryCards.size() < 2) return new ArrayList<>();

        List<CardObj> result = new ArrayList<>(four);
        result.addAll(carryCards.subList(0, 2));
        return result;
    }

    private static List<CardObj> findTwoMinCardsExcept(List<CardObj> handCards, int excludeValue) {
        return handCards.stream()
                .filter(c -> c.cardMod != excludeValue)
                .sorted()
                .limit(2)
                .collect(Collectors.toList());
    }

    private static CardObj findSmallCard(List<CardObj> handCards, int maxValue) {
        return handCards.stream()
                .filter(c -> c.cardMod <= maxValue)
                .min(Comparator.comparingInt(CardObj::getCardMod))
                .orElse(null);
    }

    private static CardObj findSmallNonBigCard(List<CardObj> handCards) {
        return handCards.stream()
                .filter(c -> c.cardMod < CARD_K)
                .min(Comparator.comparingInt(CardObj::getCardMod))
                .orElse(CardUtil.findMinSingleCard(handCards));
    }

    private static List<CardObj> findSmallestPair(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        return groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 2)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 2))
                .findFirst()
                .orElse(new ArrayList<>());
    }

    private static List<CardObj> findSmallPair(List<CardObj> handCards, int maxValue) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        return groups.entrySet().stream()
                .filter(e -> e.getKey() <= maxValue && e.getValue().size() >= 2)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 2))
                .findFirst()
                .orElse(new ArrayList<>());
    }

    private static List<CardObj> findSmallestStraight(List<CardObj> handCards) {
        for (int len = MIN_STRAIGHT_LENGTH; len <= 12; len++) {
            List<List<CardObj>> straights = findAllStraights(handCards, len);
            if (!straights.isEmpty()) {
                return straights.stream()
                        .sorted(Comparator.comparingInt(s -> s.get(0).cardMod))
                        .findFirst()
                        .get();
            }
        }
        return new ArrayList<>();
    }

    private static List<List<CardObj>> findAllStraights(List<CardObj> handCards, int len) {
        List<List<CardObj>> straights = new ArrayList<>();
        if (len < MIN_STRAIGHT_LENGTH) return straights;

        // 湖南跑得快规则：2（CARD_2）不参与顺子主体构成，但可以作为带牌
        List<Integer> distinctValues = handCards.stream()
                .map(CardObj::getCardMod)
                .filter(value -> value != CARD_2)  // 顺子主体不能包含2
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        System.out.println("[顺子查找] 顺子主体可用牌值(已排除2): " + distinctValues.stream().map(v -> getCardName(v)).collect(Collectors.joining(",")));

        for (int i = 0; i <= distinctValues.size() - len; i++) {
            boolean isConsecutive = true;
            for (int j = 0; j < len - 1; j++) {
                if (distinctValues.get(i + j + 1) - distinctValues.get(i + j) != 1) {
                    isConsecutive = false;
                    System.out.println("[顺子查找] 序列中断: " + getCardName(distinctValues.get(i + j)) + " -> " + getCardName(distinctValues.get(i + j + 1)));
                    break;
                }
            }
            if (isConsecutive) {
                List<CardObj> straight = new ArrayList<>();
                for (int j = 0; j < len; j++) {
                    int value = distinctValues.get(i + j);
                    straight.add(CardUtil.getCard(value, handCards));
                }
                straights.add(straight);
                System.out.println("[顺子查找] 找到顺子: " + straight.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            }
        }
        
        System.out.println("[顺子查找] 总共找到" + straights.size() + "个顺子");
        return straights;
    }

    private static List<CardObj> findSmallestConsecutivePair(List<CardObj> handCards) {
        System.out.println("[最小连对] 寻找最小的连对");
        List<List<CardObj>> allPairs = findAllConsecutivePairs(handCards, MIN_CONSECUTIVE_PAIR_COUNT);
        
        if (allPairs.isEmpty()) {
            System.out.println("[最小连对] 未找到连对");
            return new ArrayList<>();
        }
        
        List<CardObj> result = allPairs.stream()
                .sorted(Comparator.comparingInt(p -> p.get(0).cardMod))
                .findFirst()
                .orElse(new ArrayList<>());
                
        System.out.println("[最小连对] 选择: " + result.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        return result;
    }

    private static List<List<CardObj>> findAllConsecutivePairs(List<CardObj> handCards, int pairCount) {
        List<List<CardObj>> consecutivePairs = new ArrayList<>();
        if (pairCount < MIN_CONSECUTIVE_PAIR_COUNT) return consecutivePairs;

        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        List<Integer> pairValues = groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 2)
                .filter(e -> e.getKey() != CARD_2)  // 连对主体不能包含2
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());
        
        System.out.println("[连对查找] 连对主体可用牌值(已排除2): " + pairValues.stream().map(v -> getCardName(v)).collect(Collectors.joining(",")));
        System.out.println("[连对查找] 寻找" + pairCount + "连对");

        for (int i = 0; i <= pairValues.size() - pairCount; i++) {
            boolean isConsecutive = true;
            List<Integer> currentSequence = new ArrayList<>();
            
            for (int j = 0; j < pairCount; j++) {
                currentSequence.add(pairValues.get(i + j));
                if (j < pairCount - 1) {
                    if (pairValues.get(i + j + 1) - pairValues.get(i + j) != 1) {
                        isConsecutive = false;
                        System.out.println("[连对查找] 序列中断: " + getCardName(pairValues.get(i + j)) + " -> " + getCardName(pairValues.get(i + j + 1)));
                        break;
                    }
                }
            }
            
            if (isConsecutive) {
                List<CardObj> pairs = new ArrayList<>();
                for (int j = 0; j < pairCount; j++) {
                    pairs.addAll(groups.get(pairValues.get(i + j)).subList(0, 2));
                }
                consecutivePairs.add(pairs);
                System.out.println("[连对查找] 找到连对: " + pairs.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            }
        }
        
        System.out.println("[连对查找] 总共找到" + consecutivePairs.size() + "个连对");
        return consecutivePairs;
    }

    private static List<CardObj> findSmallestTrio(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        return groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 3)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 3))
                .findFirst()
                .orElse(new ArrayList<>());
    }

    /** 辅助方法：找出三带二中的携带牌 */
    private static CardObj findCarryCardInTrioWithTwo(List<CardObj> trioWithTwo, List<CardObj> handCards) {
        if (trioWithTwo.size() != 5) return null;
        
        // 统计各牌值的数量
        Map<Integer, Long> valueCounts = trioWithTwo.stream()
                .collect(Collectors.groupingBy(CardObj::getCardMod, Collectors.counting()));
        
        // 找出数量为1或2的牌值（携带牌）
        for (Map.Entry<Integer, Long> entry : valueCounts.entrySet()) {
            if (entry.getValue() == 1 || entry.getValue() == 2) {
                return trioWithTwo.stream()
                        .filter(card -> card.cardMod == entry.getKey())
                        .findFirst()
                        .orElse(null);
            }
        }
        
        return null;
    }
    
    private static List<CardObj> findSmallestTrioWithTwo(List<CardObj> handCards) {
        System.out.println("[主动三带二] 寻找最优的三带二组合");
        
        List<CardObj> trio = findSmallestTrio(handCards);
        if (trio.isEmpty()) {
            System.out.println("[主动三带二] 未找到三张");
            return new ArrayList<>();
        }
        
        System.out.println("[主动三带二] 找到三张: " + getCardName(trio.get(0).cardMod));

        // 使用智能携带策略
        List<CardObj> carryCards = selectOptimalCarryCards(handCards, trio.get(0).cardMod);
        
        if (carryCards.size() < 2) {
            System.out.println("[主动三带二] 未找到足够的携带牌");
            return new ArrayList<>();
        }
        
        System.out.println("[主动三带二] 选择携带: " + carryCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));

        List<CardObj> result = new ArrayList<>(trio);
        result.addAll(carryCards.subList(0, 2));
        
        System.out.println("[主动三带二] 最终出牌: " + result.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        return result;
    }

    private static List<CardObj> findSmallestBomb(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        return groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 4)
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getValue().subList(0, 4))
                .findFirst()
                .orElse(new ArrayList<>());
    }

    private static List<CardObj> findSmallestFourWithTwo(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        Optional<Map.Entry<Integer, List<CardObj>>> fourEntry = groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 4)
                .sorted(Map.Entry.comparingByKey())
                .findFirst();

        if (!fourEntry.isPresent()) return new ArrayList<>();

        List<CardObj> carryCards = findTwoMinCardsExcept(handCards, fourEntry.get().getKey());
        if (carryCards.size() < 2) return new ArrayList<>();

        List<CardObj> result = new ArrayList<>(fourEntry.get().getValue().subList(0, 4));
        result.addAll(carryCards.subList(0, 2));
        return result;
    }

    private static List<CardObj> findSmallestAirplaneWithCards(List<CardObj> handCards) {
        for (int trioCount = MIN_AIRPLANE_TRIO_COUNT; trioCount <= 3; trioCount++) {
            List<List<CardObj>> airplanes = findAllAirplanesWithCards(handCards, trioCount);
            if (!airplanes.isEmpty()) {
                return airplanes.stream()
                        .sorted(Comparator.comparingInt(a -> a.get(0).cardMod))
                        .findFirst()
                        .get();
            }
        }
        return new ArrayList<>();
    }

    /**
     * 智能查找所有可能的飞机带牌组合
     * 支持多种带牌方式：对子、单牌、混合带牌
     * 优化目标：最大化剩余手牌的价值和灵活性
     */
    private static List<List<CardObj>> findAllAirplanesWithCards(List<CardObj> handCards, int trioCount) {
        List<List<CardObj>> airplanes = new ArrayList<>();
        if (trioCount < MIN_AIRPLANE_TRIO_COUNT) return airplanes;

        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        List<Integer> trioValues = groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 3)
                .filter(e -> e.getKey() != CARD_2)  // 飞机主体(三张序列)不能包含2
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());
        
        System.out.println("[飞机查找] 飞机主体可用三张牌值(已排除2): " + trioValues.stream().map(v -> getCardName(v)).collect(Collectors.joining(",")));

        // 查找所有连续的三张序列
        for (int i = 0; i <= trioValues.size() - trioCount; i++) {
            boolean isConsecutive = true;
            for (int j = 0; j < trioCount - 1; j++) {
                if (trioValues.get(i + j + 1) - trioValues.get(i + j) != 1) {
                    isConsecutive = false;
                    break;
                }
            }
            
            if (isConsecutive) {
                // 构建基础飞机（三张部分）
                List<CardObj> baseAirplane = new ArrayList<>();
                Set<Integer> usedValues = new HashSet<>();
                for (int j = 0; j < trioCount; j++) {
                    int value = trioValues.get(i + j);
                    baseAirplane.addAll(groups.get(value).subList(0, 3));
                    usedValues.add(value);
                }
                
                // 智能选择带牌策略
                List<List<CardObj>> carryOptions = findOptimalCarryCards(handCards, usedValues, trioCount * 2);
                
                // 为每种带牌方案生成完整的飞机
                for (List<CardObj> carryCards : carryOptions) {
                    List<CardObj> completeAirplane = new ArrayList<>(baseAirplane);
                    completeAirplane.addAll(carryCards);
                    airplanes.add(completeAirplane);
                }
            }
        }
        return airplanes;
    }
    
    /**
     * 智能选择最优的带牌组合
     * 支持：对子、单牌、混合带牌
     * 策略：优先保持剩余手牌的完整性
     */
    private static List<List<CardObj>> findOptimalCarryCards(List<CardObj> handCards, Set<Integer> usedValues, int requiredCarryCount) {
        List<List<CardObj>> options = new ArrayList<>();
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        
        // 获取可用的牌（排除已用于飞机的三张）
        List<CardObj> availableCards = handCards.stream()
                .filter(card -> !usedValues.contains(card.cardMod))
                .collect(Collectors.toList());
        
        System.out.println("[飞机带牌] 可用于带牌的牌: " + 
            availableCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        
        // 策略1：优先带对子（保持牌型完整性）
        List<CardObj> pairCarry = findBestPairCarry(groups, usedValues, requiredCarryCount);
        if (!pairCarry.isEmpty()) {
            options.add(pairCarry);
            System.out.println("[飞机带牌] 策略1-对子带牌: " + 
                pairCarry.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        }
        
        // 策略2：带单牌（消耗孤立单牌）
        List<CardObj> singleCarry = findBestSingleCarry(availableCards, requiredCarryCount);
        if (!singleCarry.isEmpty()) {
            options.add(singleCarry);
            System.out.println("[飞机带牌] 策略2-单牌带牌: " + 
                singleCarry.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        }
        
        // 策略3：混合带牌（对子+单牌）
        List<CardObj> mixedCarry = findBestMixedCarry(groups, availableCards, usedValues, requiredCarryCount);
        if (!mixedCarry.isEmpty()) {
            options.add(mixedCarry);
            System.out.println("[飞机带牌] 策略3-混合带牌: " + 
                mixedCarry.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        }
        
        return options;
    }
    
    /** 查找最优对子带牌方案 */
    private static List<CardObj> findBestPairCarry(Map<Integer, List<CardObj>> groups, Set<Integer> usedValues, int requiredCount) {
        List<CardObj> carryCards = new ArrayList<>();
        List<Map.Entry<Integer, List<CardObj>>> pairCandidates = groups.entrySet().stream()
                .filter(e -> !usedValues.contains(e.getKey()) && e.getValue().size() >= 2)
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toList());
        
        int pairsNeeded = requiredCount / 2;
        if (pairCandidates.size() >= pairsNeeded) {
            for (int i = 0; i < pairsNeeded; i++) {
                carryCards.addAll(pairCandidates.get(i).getValue().subList(0, 2));
            }
        }
        return carryCards;
    }
    
    /** 查找最优单牌带牌方案 - 智能保护组合结构 */
    private static List<CardObj> findBestSingleCarry(List<CardObj> availableCards, int requiredCount) {
        System.out.println("[飞机单牌带牌] 分析安全单牌选择");
        
        // 优先选择不会破坏组合结构的安全单牌
        List<CardObj> safeSingleCards = availableCards.stream()
                .filter(card -> {
                    Map<Integer, List<CardObj>> tempGroups = CardUtil.getCardListMap(availableCards);
                    return tempGroups.get(card.cardMod).size() == 1; // 确保是单牌
                })
                .filter(card -> !wouldBreakComboStructure(card, availableCards)) // 避免破坏组合
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        System.out.println("[飞机单牌带牌] 安全单牌: " + 
            safeSingleCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        
        if (safeSingleCards.size() >= requiredCount) {
            List<CardObj> selected = safeSingleCards.subList(0, requiredCount);
            System.out.println("[飞机单牌带牌] 选择安全单牌: " + 
                selected.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            return selected;
        }
        
        // 如果没有足够的安全单牌，考虑带2（但要非常谨慎）
        List<CardObj> twoCards = availableCards.stream()
                .filter(card -> card.cardMod == CARD_2)
                .collect(Collectors.toList());
        
        if (!twoCards.isEmpty() && wouldAllowCarryingTwo(availableCards, requiredCount)) {
            System.out.println("[飞机单牌带牌] 特殊情况：允许带2");
            List<CardObj> result = new ArrayList<>();
            result.addAll(twoCards);
            // 补充其他安全单牌
            int remainingNeeded = requiredCount - twoCards.size();
            if (remainingNeeded > 0) {
                List<CardObj> otherSingles = safeSingleCards.stream()
                        .filter(card -> card.cardMod != CARD_2)
                        .limit(remainingNeeded)
                        .collect(Collectors.toList());
                result.addAll(otherSingles);
            }
            if (result.size() == requiredCount) {
                System.out.println("[飞机单牌带牌] 带2方案成功: " + 
                    result.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
                return result;
            }
        }
        
        System.out.println("[飞机单牌带牌] 无足够安全单牌");
        return new ArrayList<>();
    }
    
    /** 判断是否允许带2 - 更加灵活的判断 */
    private static boolean wouldAllowCarryingTwo(List<CardObj> availableCards, int requiredCount) {
        // 移除2后分析剩余牌的组合潜力
        List<CardObj> withoutTwos = availableCards.stream()
                .filter(card -> card.cardMod != CARD_2)
                .collect(Collectors.toList());
        
        ComboPotential potential = analyzeComboPotential(withoutTwos);
        
        // 如果移除2后仍有良好的组合结构，则允许带2
        boolean hasGoodStructure = potential.hasGoodStructure();
        
        System.out.println("[带2判断] 移除2后剩余牌潜力: " + potential + ", 结构良好: " + hasGoodStructure);
        
        return hasGoodStructure;
    }

    /** 查找最优混合带牌方案 */
    private static List<CardObj> findBestMixedCarry(Map<Integer, List<CardObj>> groups, 
            List<CardObj> availableCards, Set<Integer> usedValues, int requiredCount) {
        List<CardObj> carryCards = new ArrayList<>();
        
        // 先拿对子
        List<Map.Entry<Integer, List<CardObj>>> pairCandidates = groups.entrySet().stream()
                .filter(e -> !usedValues.contains(e.getKey()) && e.getValue().size() >= 2)
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toList());
        
        // 拿尽可能多的对子
        int pairsTaken = 0;
        for (Map.Entry<Integer, List<CardObj>> entry : pairCandidates) {
            if (pairsTaken * 2 + 2 <= requiredCount) {
                carryCards.addAll(entry.getValue().subList(0, 2));
                pairsTaken++;
            } else {
                break;
            }
        }
        
        // 补充单牌
        int remainingNeeded = requiredCount - carryCards.size();
        if (remainingNeeded > 0) {
            List<CardObj> singleCards = availableCards.stream()
                    .filter(card -> !carryCards.contains(card))
                    .filter(card -> {
                        Map<Integer, List<CardObj>> tempGroups = CardUtil.getCardListMap(availableCards);
                        return tempGroups.get(card.cardMod).size() == 1;
                    })
                    .sorted(Comparator.comparingInt(CardObj::getCardMod))
                    .collect(Collectors.toList());
            
            if (singleCards.size() >= remainingNeeded) {
                carryCards.addAll(singleCards.subList(0, remainingNeeded));
            }
        }
        
        return carryCards.size() == requiredCount ? carryCards : new ArrayList<>();
    }

    private static int findMaxStraightLength(List<CardObj> handCards) {
        List<Integer> distinctValues = handCards.stream()
                .map(CardObj::getCardMod)
                .distinct()
                .sorted()
                .collect(Collectors.toList());
        
        int maxLength = 0;
        int currentLength = 1;
        
        for (int i = 1; i < distinctValues.size(); i++) {
            if (distinctValues.get(i) - distinctValues.get(i-1) == 1) {
                currentLength++;
            } else {
                maxLength = Math.max(maxLength, currentLength);
                currentLength = 1;
            }
        }
        maxLength = Math.max(maxLength, currentLength);
        
        return maxLength;
    }
    
    private static int findMaxConsecutivePairs(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        List<Integer> pairValues = groups.entrySet().stream()
                .filter(e -> e.getValue().size() >= 2)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());
        
        if (pairValues.isEmpty()) return 0;
        
        int maxPairs = 1;
        int currentPairs = 1;
        
        for (int i = 1; i < pairValues.size(); i++) {
            if (pairValues.get(i) - pairValues.get(i-1) == 1) {
                currentPairs++;
            } else {
                maxPairs = Math.max(maxPairs, currentPairs);
                currentPairs = 1;
            }
        }
        maxPairs = Math.max(maxPairs, currentPairs);
        
        return maxPairs;
    }


    /**
     * 改进的牌型推断方法 - 修复连对识别错误
     * 修复要点：4张牌优先推断为连对而非炸弹
     */
    private static int inferCorrectCardType(int len) {
        // 优先处理常见的连对情况
        if (len == 4) return TYPE_CONSECUTIVE_PAIR;  // 2连对（最常见错误场景）
        if (len == 6) return TYPE_CONSECUTIVE_PAIR;  // 3连对
        if (len == 8) return TYPE_CONSECUTIVE_PAIR;  // 4连对
        if (len == 10) return TYPE_CONSECUTIVE_PAIR; // 5连对
        if (len == 12) return TYPE_AIRPLANE_WITH_CARDS; // 飞机
        
        // 基础牌型
        switch (len) {
            case 1: return TYPE_SINGLE;
            case 2: return TYPE_PAIR;
            case 3: return TYPE_TRIO;
            case 4: return TYPE_CONSECUTIVE_PAIR;  // 修复：4张牌优先推断为连对
            case 5: return TYPE_TRIO_WITH_TWO;
            case 6: return TYPE_CONSECUTIVE_PAIR;
            default:
                // 连对：偶数张且>=4
                if (len >= 4 && len % 2 == 0) return TYPE_CONSECUTIVE_PAIR;
                // 顺子：连续5张以上
                if (len >= MIN_STRAIGHT_LENGTH) return TYPE_STRAIGHT;
                // 飞机：3的倍数且>=6
                if (len >= MIN_AIRPLANE_TRIO_COUNT * 5 && len % 5 == 0) return TYPE_AIRPLANE_WITH_CARDS;
                // 真正的炸弹：必须明确是4张相同牌
                if (len == 4) return TYPE_BOMB;  // 只有在确定是炸弹时才返回
                return TYPE_SINGLE;
        }
    }

    /** 检查是否有对手只剩两张牌 */
    private static boolean checkIfAnyOpponentHasTwoCards(Map<Integer, List<Integer>> seatRemainHistory, int currentSeat) {
        if (seatRemainHistory == null || seatRemainHistory.isEmpty()) {
            return false;
        }
        
        for (Map.Entry<Integer, List<Integer>> entry : seatRemainHistory.entrySet()) {
            int seat = entry.getKey();
            List<Integer> remainList = entry.getValue();
            
            if (seat == currentSeat) {
                continue;
            }
            
            if (remainList != null && !remainList.isEmpty()) {
                int lastRemain = remainList.get(remainList.size() - 1);
                if (lastRemain == 2) {
                    System.out.println("[对手检测] 检测到对手(座位" + seat + ")只剩两张牌，启动试探策略");
                    return true;
                }
            }
        }
        return false;
    }
    
    private static boolean checkIfAnyOpponentHasOneCard(Map<Integer, List<Integer>> seatRemainHistory, int currentSeat) {
        if (seatRemainHistory == null || seatRemainHistory.isEmpty()) {
            return false;
        }
        
        for (Map.Entry<Integer, List<Integer>> entry : seatRemainHistory.entrySet()) {
            int seat = entry.getKey();
            List<Integer> remainList = entry.getValue();
            
            if (seat == currentSeat) {
                continue;
            }
            
            if (remainList != null && !remainList.isEmpty()) {
                int lastRemain = remainList.get(remainList.size() - 1);
                if (lastRemain == 1) {
                    return true;
                }
            }
        }
        return false;
    }
    
    /** 检查自身是否处于残局状态（手中牌较少）*/
    private static boolean checkIfSelfInEndgame(List<CardObj> handCards) {
        if (handCards == null || handCards.isEmpty()) return false;
        
        // 当手中牌数少于等于4张时认为进入残局
        if (handCards.size() <= 4) {
            System.out.println("[自我残局检测] 手中剩余牌数: " + handCards.size() + "，进入残局模式");
            return true;
        }
        
        // 或者当手中大部分都是单牌时也认为是残局
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        long singleCardCount = groups.values().stream().filter(list -> list.size() == 1).count();
        double singleCardRatio = (double) singleCardCount / handCards.size();
        
        if (singleCardRatio >= 0.7) {  // 70%以上都是单牌
            System.out.println("[自我残局检测] 单牌比例: " + String.format("%.1f", singleCardRatio*100) + "%，进入残局模式");
            return true;
        }
        
        return false;
    }
    
    /** 自身残局处理策略 - 关键改进！*/
    private static ITArray handleSelfEndgameSituation(List<CardObj> handCards) {
        System.out.println("[自我残局策略] 优化后的残局处理");
        
        // 1. 首先检查是否有组合牌型可以出（优先级最高）
        List<CardObj> comboMove = findBestEndgameCombo(handCards);
        if (!comboMove.isEmpty()) {
            System.out.println("[自我残局] 优先出组合牌型: " + comboMove.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
            return CardUtil.toTArray(comboMove);
        }
        
        // 2. 如果没有组合牌型，寻找最小的有效出牌
        List<CardObj> minimalMove = findMinimalEffectiveMove(handCards);
        if (!minimalMove.isEmpty()) {
            System.out.println("[自我残局] 出最小有效牌组: " + minimalMove.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
            return CardUtil.toTArray(minimalMove);
        }
        
        // 3. 最后兜底
        System.out.println("[自我残局] 无有效出牌选择，紧急处理");
        return emergencyOutCard(handCards);
    }
    
    /** 寻找最小有效出牌（避免拆分有价值组合）*/
    private static List<CardObj> findMinimalEffectiveMove(List<CardObj> handCards) {
        System.out.println("[最小有效出牌] 寻找不会破坏牌型结构的最小出牌");
        
        // 1. 寻找最小的对子
        List<CardObj> smallestPair = findSmallestPair(handCards);
        if (!smallestPair.isEmpty()) {
            System.out.println("[最小出牌] 发现最小对子");
            return smallestPair;
        }
        
        // 2. 寻找最小的三张
        List<CardObj> smallestTrio = findSmallestTrio(handCards);
        if (!smallestTrio.isEmpty()) {
            System.out.println("[最小出牌] 发现最小三张");
            return smallestTrio;
        }
        
        // 3. 寻找最小的单牌（但要避免拆分即将成型的组合）
        CardObj smallestSingle = findSafeSingleCard(handCards);
        if (smallestSingle != null) {
            System.out.println("[最小出牌] 出最小安全单牌: " + getCardName(smallestSingle.cardMod));
            return Collections.singletonList(smallestSingle);
        }
        
        System.out.println("[最小出牌] 无安全出牌选择");
        return new ArrayList<>();
    }
    
    /** 寻找安全的单牌（避免拆分有价值的组合）*/
    private static CardObj findSafeSingleCard(List<CardObj> handCards) {
        // 先统计牌型分布
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        List<CardObj> singleCards = new ArrayList<>();
        
        // 收集所有单牌
        for (List<CardObj> group : groups.values()) {
            if (group.size() == 1) {
                singleCards.add(group.get(0));
            }
        }
        
        if (singleCards.isEmpty()) {
            return null;
        }
        
        // 优先选择最小的单牌
        singleCards.sort(Comparator.comparingInt(CardObj::getCardMod));
        
        // 检查这张牌是否可能参与形成更好的组合
        CardObj candidate = singleCards.get(0);
        
        // 如果这张牌太小（3-5），且手牌较多，可以安全出
        if (candidate.cardMod <= CARD_5 && handCards.size() > 3) {
            return candidate;
        }
        
        // 如果手牌很少（<=3张），优先出最小的
        if (handCards.size() <= 3) {
            return candidate;
        }
        
        // 其他情况下，选择相对较小但不太影响后续组合的牌
        for (CardObj card : singleCards) {
            if (card.cardMod <= CARD_8) {  // 限制在8以下
                return card;
            }
        }
        
        // 如果都没有合适的，就出最小的
        return candidate;
    }

    private static String getCardName(int cardMod) {
        switch (cardMod) {
            case CARD_3: return "3";
            case CARD_4: return "4";
            case CARD_5: return "5";
            case CARD_6: return "6";
            case CARD_7: return "7";
            case CARD_8: return "8";
            case CARD_9: return "9";
            case CARD_10: return "10";
            case CARD_J: return "J";
            case CARD_Q: return "Q";
            case CARD_K: return "K";
            case CARD_A: return "A";
            case CARD_2: return "2";
            default: return String.valueOf(cardMod);
        }
    }

    private static String getCardTypeName(int type) {
        switch (type) {
            case TYPE_SINGLE: return "单牌";
            case TYPE_PAIR: return "对子";
            case TYPE_STRAIGHT: return "顺子";
            case TYPE_CONSECUTIVE_PAIR: return "连对";
            case TYPE_TRIO: return "三张";
            case TYPE_TRIO_WITH_TWO: return "三带二";
            case TYPE_BOMB: return "炸弹";
            case TYPE_AIRPLANE_WITH_CARDS: return "飞机带牌";
            case TYPE_FOUR_WITH_TWO: return "四带二";
            case TYPE_FOUR_WITH_TWO_PAIR: return "四带二对";
            default: return "非法/未知(" + type + ")";
        }
    }

    /**
     * 智能牌型纠错 - 根据常见模式和牌数推断正确牌型
     * 修复跑得快游戏中常见的牌型识别错误
     */
    private static int correctCardTypeByPattern(int reportedType, int len, int minCard) {
        System.out.println("[模式纠错] 分析牌型 - 报告类型:" + getCardTypeName(reportedType) + ", 牌数:" + len + ", 最小牌:" + getCardName(minCard));
        
        // 典型错误情况1：4张牌被错误报告为炸弹（最常见错误）
        if (reportedType == TYPE_BOMB && len == 4) {
            System.out.println("[模式纠错] ⚠️ 检测到4张牌被报告为炸弹，极可能是连对错误识别");
            System.out.println("[模式纠错] 建议：将类型从炸弹纠正为连对");
            return TYPE_CONSECUTIVE_PAIR;  // 强制纠正为连对
        }
        
        // 典型错误情况2：TYPE_CONSECUTIVE_PAIR(4)被错误使用
        if (reportedType == TYPE_CONSECUTIVE_PAIR && len == 4) {
            // 这是正常的连对，不需要纠正
            System.out.println("[模式纠错] 4张牌正确识别为连对");
            return reportedType;
        }
        
        // 典型错误情况3：连对被错误报告为其他类型
        if (len >= 4 && len % 2 == 0) {
            // 偶数张牌很可能是连对
            if (reportedType != TYPE_CONSECUTIVE_PAIR && reportedType != TYPE_BOMB) {
                System.out.println("[模式纠错] 偶数张牌(" + len + "张)更可能是连对");
                return TYPE_CONSECUTIVE_PAIR;
            }
        }
        
        // 典型错误情况4：5-12张牌的合理判断
        if (len >= 5 && len <= 12) {
            // 5张牌的特殊处理：需要根据具体内容判断
            if (len == 5 && reportedType == TYPE_TRIO_WITH_TWO) {
                // 5张三带二是合理的牌型，不应该盲目纠正为顺子
                System.out.println("[模式纠错] 5张牌报告为三带二是合理的牌型");
                // 不进行纠正，保持原类型
                return reportedType;
            }
            
            // 其他连续牌情况
            if (reportedType == TYPE_SINGLE || reportedType == TYPE_PAIR) {
                System.out.println("[模式纠错] " + len + "张连续牌更可能是顺子");
                return TYPE_STRAIGHT;
            }
        }
        
        // 典型错误情况5：连对与炸弹混淆（特别是3344这种情况）
        if (len == 4) {
            // 4张牌时，强烈倾向于连对而非炸弹
            if (reportedType == TYPE_BOMB) {
                System.out.println("[模式纠错] ⚠️ 4张牌被报告为炸弹，极可能是连对错误识别");
                System.out.println("[模式纠错] 建议：将类型从炸弹纠正为连对");
                return TYPE_CONSECUTIVE_PAIR;
            }
            // 如果已经是连对，保持不变
            if (reportedType == TYPE_CONSECUTIVE_PAIR) {
                System.out.println("[模式纠错] 4张牌正确识别为连对");
                return reportedType;
            }
        }
        
        // 如果没有发现明显错误，返回原始类型
        System.out.println("[模式纠错] 未发现明显错误，保持原始类型");
        return reportedType;
    }

    /**
     * 智能分析实际牌型 - 真正的AI核心！
     * 修复各种牌型识别错误，包括连对vs炸弹、顺子vs三带二等
     */
    private static int analyzeActualCardType(List<CardObj> cards) {
        if (cards == null || cards.isEmpty()) return TYPE_SINGLE;
        
        System.out.println("[牌型分析] 分析牌面: " + cards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        
        // 1. 统计每种牌的数量
        Map<Integer, Long> countMap = cards.stream()
                .collect(Collectors.groupingBy(CardObj::getCardMod, Collectors.counting()));
        
        System.out.println("[牌型分析] 牌数统计: " + countMap);
        
        // 2. 分析牌型特征
        int cardCount = cards.size();
        List<Integer> uniqueValues = new ArrayList<>(countMap.keySet());
        Collections.sort(uniqueValues);
        
        // 单牌
        if (cardCount == 1) {
            System.out.println("[牌型分析] 结论: 单牌");
            return TYPE_SINGLE;
        }
        
        // 对子
        if (cardCount == 2 && uniqueValues.size() == 1 && countMap.get(uniqueValues.get(0)) == 2) {
            System.out.println("[牌型分析] 结论: 对子");
            return TYPE_PAIR;
        }
        
        // 三张
        if (cardCount == 3 && uniqueValues.size() == 1 && countMap.get(uniqueValues.get(0)) == 3) {
            System.out.println("[牌型分析] 结论: 三张");
            return TYPE_TRIO;
        }
        
        // 炸弹 vs 连对的关键判断（4张牌）
        if (cardCount == 4) {
            if (uniqueValues.size() == 1 && countMap.get(uniqueValues.get(0)) == 4) {
                // 真正的炸弹：四张相同
                System.out.println("[牌型分析] 结论: 炸弹 (四张" + getCardName(uniqueValues.get(0)) + ")");
                return TYPE_BOMB;
            } else if (uniqueValues.size() == 2 && 
                       countMap.get(uniqueValues.get(0)) == 2 && 
                       countMap.get(uniqueValues.get(1)) == 2 &&
                       uniqueValues.get(1) - uniqueValues.get(0) == 1) {
                // 连对：两个连续的对子
                System.out.println("[牌型分析] 结论: 连对 (" + getCardName(uniqueValues.get(0)) + getCardName(uniqueValues.get(0)) + 
                                 getCardName(uniqueValues.get(1)) + getCardName(uniqueValues.get(1)) + ")");
                return TYPE_CONSECUTIVE_PAIR;
            } else {
                System.out.println("[牌型分析] 结论: 4张牌无法识别，按单牌处理");
                return TYPE_SINGLE;
            }
        }
        
        // 连对：检查是否全是对子且数值连续（6张及以上）
        if (cardCount >= 6 && cardCount % 2 == 0) {
            boolean allPairs = uniqueValues.stream().allMatch(v -> countMap.get(v) == 2);
            boolean consecutive = isConsecutive(uniqueValues);
            
            if (allPairs && consecutive) {
                int pairCount = cardCount / 2;
                System.out.println("[牌型分析] 结论: 连对 (" + pairCount + "连对，共" + cardCount + "张牌)");
                return TYPE_CONSECUTIVE_PAIR;
            }
        }
        
        // 顺子：检查是否无重复且连续（5张及以上）
        if (cardCount >= 5) {
            boolean noDuplicates = uniqueValues.size() == cardCount;
            boolean consecutive = isConsecutive(uniqueValues);
            
            if (noDuplicates && consecutive) {
                StringBuilder sb = new StringBuilder();
                for (Integer val : uniqueValues) {
                    sb.append(getCardName(val));
                }
                System.out.println("[牌型分析] 结论: 顺子 (" + cardCount + "张: " + sb.toString() + ")");
                return TYPE_STRAIGHT;
            }
        }
        
        // 三带二
        if (cardCount == 5) {
            boolean hasThree = uniqueValues.stream().anyMatch(v -> countMap.get(v) == 3);
            // 三带二有两种情况：三带一对，或者三带两张单牌
            boolean hasValidCarry = uniqueValues.size() == 2 || uniqueValues.size() == 3; // 2种不同牌值(三带对)或3种不同牌值(三带两张单牌)
            
            if (hasThree && hasValidCarry) {
                System.out.println("[牌型分析] 结论: 三带二");
                return TYPE_TRIO_WITH_TWO;
            }
            
            // 特殊情况：5张连续牌也可能是顺子
            boolean noDuplicates = uniqueValues.size() == cardCount;
            boolean consecutive = isConsecutive(uniqueValues);
            if (noDuplicates && consecutive) {
                System.out.println("[牌型分析] 结论: 顺子 (5张连续牌)");
                return TYPE_STRAIGHT;
            }
        }
        
        // 四带二系列
        if (cardCount == 6) {
            boolean hasFour = uniqueValues.stream().anyMatch(v -> countMap.get(v) == 4);
            if (hasFour) {
                System.out.println("[牌型分析] 结论: 四带二");
                return TYPE_FOUR_WITH_TWO;
            }
        }
        
        if (cardCount == 8) {
            boolean hasFour = uniqueValues.stream().anyMatch(v -> countMap.get(v) == 4);
            long pairCount = uniqueValues.stream().filter(v -> countMap.get(v) == 2).count();
            if (hasFour && pairCount >= 2) {
                System.out.println("[牌型分析] 结论: 四带二对");
                return TYPE_FOUR_WITH_TWO_PAIR;
            }
        }
        
        // 默认返回单牌
        System.out.println("[牌型分析] 结论: 无法精确识别，按单牌处理");
        return TYPE_SINGLE;
    }
    
    /** 判断数值是否连续 */
    private static boolean isConsecutive(List<Integer> values) {
        if (values.size() < 2) return true;
        
        for (int i = 1; i < values.size(); i++) {
            if (values.get(i) - values.get(i-1) != 1) {
                return false;
            }
        }
        return true;
    }
    
    /** 潜在结构分析 - 评估拆分某张牌对顺子形成的影响 */
    private static PotentialImpact analyzePotentialImpact(List<CardObj> handCards, CardObj targetCard) {
        // 1. 移除目标牌后重新分析手牌
        List<CardObj> remainingCards = new ArrayList<>(handCards);
        remainingCards.remove(targetCard);
        
        // 2. 全面评估移除前后的牌型结构变化
        ComprehensiveImpact impact = evaluateComprehensiveStructuralImpact(handCards, remainingCards);
        
        // 3. 综合评分：破坏顺子数×100 + 破坏连对数×50 + 牌面值
        int impactScore = impact.destroyedStraights * 100 + impact.destroyedPairs * 50 + targetCard.cardMod;
        
        System.out.println("[影响分析] 出" + getCardName(targetCard.cardMod) + 
                          "会破坏" + impact.destroyedStraights + "个顺子, " + 
                          impact.destroyedPairs + "个连对");
        
        return new PotentialImpact(targetCard, impactScore, impact.destroyedStraights > 0, impact.destroyedPairs > 0);
    }
    
    /** 全面评估结构性影响 */
    private static ComprehensiveImpact evaluateComprehensiveStructuralImpact(List<CardObj> originalCards, List<CardObj> remainingCards) {
        // 分析原始手牌的组合结构
        List<List<CardObj>> originalStraights = findAllStraights(originalCards, 5);
        List<List<CardObj>> originalPairs = findAllConsecutivePairs(originalCards, 2);
        
        // 分析剩余手牌的组合结构
        List<List<CardObj>> remainingStraights = findAllStraights(remainingCards, 5);
        List<List<CardObj>> remainingPairs = findAllConsecutivePairs(remainingCards, 2);
        
        // 计算被破坏的结构数量
        int destroyedStraights = Math.max(0, originalStraights.size() - remainingStraights.size());
        int destroyedPairs = Math.max(0, originalPairs.size() - remainingPairs.size());
        
        return new ComprehensiveImpact(destroyedStraights, destroyedPairs);
    }
    
    /** 综合影响评估类 */
    private static class ComprehensiveImpact {
        int destroyedStraights;
        int destroyedPairs;
        
        ComprehensiveImpact(int destroyedStraights, int destroyedPairs) {
            this.destroyedStraights = destroyedStraights;
            this.destroyedPairs = destroyedPairs;
        }
    }

    /** 潜在影响评估类 */
    private static class PotentialImpact {
        CardObj card;
        int impactScore;  // 影响分数，正值表示负面影响
        boolean breaksStraight;
        boolean breaksPairs;
        
        PotentialImpact(CardObj card, int impactScore, boolean breaksStraight, boolean breaksPairs) {
            this.card = card;
            this.impactScore = impactScore;
            this.breaksStraight = breaksStraight;
            this.breaksPairs = breaksPairs;
        }
        
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(getCardName(card.cardMod)).append("(影响度:").append(impactScore);
            if (breaksStraight) sb.append("[破坏顺子]");
            if (breaksPairs) sb.append("[破坏连对]");
            sb.append(")");
            return sb.toString();
        }
    }
    
    /** 智能单牌选择 - 考虑组合结构保护 */
    private static CardObj findSmartSingleCard(List<CardObj> handCards, int minCard) {
        List<CardObj> singleCards = handCards.stream()
                .filter(c -> CardUtil.getCardNumMap(handCards).get(c.cardMod) == 1)
                .filter(c -> c.cardMod > minCard)
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        if (singleCards.isEmpty()) return null;
        
        System.out.println("[智能单牌] 可选单牌: " + singleCards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        
        // 分析每个单牌的潜在影响
        List<PotentialImpact> impacts = new ArrayList<>();
        for (CardObj card : singleCards) {
            PotentialImpact impact = analyzePotentialImpact(handCards, card);
            impacts.add(impact);
            System.out.println("[智能分析] " + impact.toString());
        }
        
        // 简化排序：优先选择影响最小的单牌
        PotentialImpact bestChoice = impacts.stream()
                .min(Comparator.comparingInt(i -> i.impactScore))
                .orElse(null);
        
        if (bestChoice != null) {
            System.out.println("[智能决策] 选择影响最小的单牌: " + getCardName(bestChoice.card.cardMod) + 
                             " (影响度:" + bestChoice.impactScore + ")");
            return bestChoice.card;
        }
        
        // 兜底选择
        CardObj minCardObj = singleCards.get(0);
        System.out.println("[智能决策] 兜底选择最小单牌: " + getCardName(minCardObj.cardMod));
        return minCardObj;
    }
    
    /** 智能拆牌选择 - 当必须拆组合牌时的最优选择 */
    private static CardObj findBestCardToBreak(List<CardObj> handCards, int minCard) {
        System.out.println("[拆牌策略] 分析可拆组合牌的选择");
        
        // 收集所有大于minCard的牌（包括组合中的牌）
        List<CardObj> candidates = handCards.stream()
                .filter(c -> c.cardMod > minCard)
                .sorted(Comparator.comparingInt(CardObj::getCardMod))
                .collect(Collectors.toList());
        
        if (candidates.isEmpty()) {
            System.out.println("[拆牌策略] 无可拆之牌");
            return null;
        }
        
        System.out.println("[拆牌策略] 可选拆牌: " + candidates.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(",")));
        
        // 分析每张牌拆掉后的手牌质量
        List<BreakImpact> breakImpacts = new ArrayList<>();
        for (CardObj card : candidates) {
            BreakImpact impact = analyzeBreakImpact(handCards, card);
            breakImpacts.add(impact);
            System.out.println("[拆牌分析] " + impact.toString());
        }
        
        // 选择拆牌代价最小的牌
        BreakImpact bestBreak = breakImpacts.stream()
                .min(Comparator.comparingDouble(b -> b.costScore))
                .orElse(null);
        
        if (bestBreak != null) {
            System.out.println("[拆牌决策] 选择最优拆牌: " + getCardName(bestBreak.card.cardMod) + 
                             " (代价分:" + String.format("%.2f", bestBreak.costScore) + ")");
            return bestBreak.card;
        }
        
        // 兜底选择最小的可拆牌
        CardObj minBreakCard = candidates.get(0);
        System.out.println("[拆牌决策] 兜底选择最小可拆牌: " + getCardName(minBreakCard.cardMod));
        return minBreakCard;
    }
    
    /** 拆牌影响分析类 */
    private static class BreakImpact {
        CardObj card;
        double costScore;      // 拆牌代价分（越小越好）
        int remainingCombos;   // 拆牌后剩余组合数
        int remainingSingles;  // 拆牌后剩余单牌数
        boolean preservesBestCombo; // 是否保留了最好的组合
        
        BreakImpact(CardObj card, double costScore, int remainingCombos, int remainingSingles, boolean preservesBestCombo) {
            this.card = card;
            this.costScore = costScore;
            this.remainingCombos = remainingCombos;
            this.remainingSingles = remainingSingles;
            this.preservesBestCombo = preservesBestCombo;
        }
        
        @Override
        public String toString() {
            return getCardName(card.cardMod) + "(代价:" + String.format("%.2f", costScore) + 
                   ", 组合:" + remainingCombos + ", 单牌:" + remainingSingles + ")";
        }
    }
    
    /** 分析拆某张牌的代价 */
    private static BreakImpact analyzeBreakImpact(List<CardObj> handCards, CardObj targetCard) {
        // 模拟拆牌后的情况
        List<CardObj> remainingCards = new ArrayList<>(handCards);
        remainingCards.remove(targetCard);
        
        // 分析剩余手牌结构
        HandAnalysis analysis = analyzeHandComposition(remainingCards);
        int originalComboCount = countTotalCombos(handCards);
        int remainingComboCount = countTotalCombos(remainingCards);
        
        // 计算代价分
        double costScore = 0.0;
        
        // 1. 组合损失惩罚（主要因素）
        int comboLoss = originalComboCount - remainingComboCount;
        costScore += comboLoss * 10.0;
        
        // 2. 牌值惩罚（避免拆大牌）
        costScore += targetCard.cardMod * 0.5;
        
        // 3. 单牌增加惩罚
        long originalSingles = CardUtil.getCardNumMap(handCards).entrySet().stream()
                .filter(e -> e.getValue() == 1).count();
        int singleIncrease = analysis.singleCount - (int)originalSingles;
        costScore += singleIncrease * 2.0;
        
        // 4. 保留最佳组合奖励
        boolean preservesBest = preservesBestCombination(handCards, remainingCards);
        if (preservesBest) costScore -= 3.0;
        
        return new BreakImpact(targetCard, costScore, remainingComboCount, 
                             analysis.singleCount, preservesBest);
    }
    
    /** 计算手牌中总的组合数 */
    private static int countTotalCombos(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        int combos = 0;
        
        // 对子
        combos += groups.values().stream().filter(list -> list.size() == 2).count();
        // 三张
        combos += groups.values().stream().filter(list -> list.size() == 3).count();
        // 炸弹
        combos += groups.values().stream().filter(list -> list.size() >= 4).count();
        
        // 顺子和连对
        combos += findAllStraights(handCards, 5).size();
        combos += findAllConsecutivePairs(handCards, 2).size();
        
        return (int) combos;
    }
    
    /** 判断是否保留了最好的组合 */
    private static boolean preservesBestCombination(List<CardObj> original, List<CardObj> remaining) {
        // 简化判断：如果剩余手牌中仍有高质量组合则认为保留了最好组合
        HandAnalysis remainingAnalysis = analyzeHandComposition(remaining);
        return remainingAnalysis.comboQualityScore > 0.5;
    }
    
    /** 调试用手牌分析 */
    private static void debugHandAnalysis(List<CardObj> handCards) {
        System.out.println("\n---------- 手牌详细分析 ----------");
        
        // 按牌值分组
        Map<Integer, List<CardObj>> groups = CardUtil.getCardListMap(handCards);
        System.out.println("牌值分布:");
        groups.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .forEach(e -> {
                    String cardNames = e.getValue().stream()
                            .map(c -> getCardName(c.cardMod))
                            .collect(Collectors.joining(""));
                    System.out.println("  " + getCardName(e.getKey()) + ": " + cardNames + " (" + e.getValue().size() + "张)");
                });
        
        // 查找所有可能的牌型
        System.out.println("\n可出牌型分析:");
        
        // 对子
        List<CardObj> pairs = findSmallestPair(handCards);
        if (!pairs.isEmpty()) {
            System.out.println("  对子: " + pairs.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
        }
        
        // 连对
        List<List<CardObj>> consecutivePairs = findAllConsecutivePairs(handCards, 2);
        if (!consecutivePairs.isEmpty()) {
            System.out.println("  连对数量: " + consecutivePairs.size());
            for (int i = 0; i < Math.min(3, consecutivePairs.size()); i++) {
                List<CardObj> pair = consecutivePairs.get(i);
                System.out.println("    连对" + (i+1) + ": " + pair.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            }
        }
        
        // 顺子
        List<List<CardObj>> straights = findAllStraights(handCards, 5);
        if (!straights.isEmpty()) {
            System.out.println("  顺子数量: " + straights.size());
            for (int i = 0; i < Math.min(2, straights.size()); i++) {
                List<CardObj> straight = straights.get(i);
                System.out.println("    顺子" + (i+1) + ": " + straight.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining("")));
            }
        }
        
        System.out.println("----------------------------------");
    }
    
    private static String getDecisionDescription(ITArray decision, List<CardObj> handCards) {
        if (decision == null || decision.size() == 0) {
            return "Pass";
        }
        
        List<CardObj> cards = CardUtil.toList(decision);
        if (cards.isEmpty()) return "Pass";
        
        String typeName = getCardTypeName(inferCorrectCardType(cards.size()));
        String cardNames = cards.stream().map(c -> getCardName(c.cardMod)).collect(Collectors.joining(","));
        return typeName + "[" + cardNames + "]";
    }
    
}