import pandas as pd
import random

# 牌组编码与生成
CARD = {
    '天': {'p': 12}, '地': {'p': 2}, '人': {'p': 8}, '和': {'p': 4},
    '梅花': {'p': 10}, '长三': {'p': 6}, '板凳': {'p': 4}, '斧头': {'p': 11},
    '红头十': {'p': 10}, '高脚七': {'p': 7}, '零霖六': {'p': 6},
    
    '红九': {'p': 9}, '黑九': {'p': 9},
    '平八': {'p': 8}, '斜八': {'p': 8},
    '红七': {'p': 7}, '黑七': {'p': 7},
    '红五': {'p': 5}, '黑五': {'p': 5},
    
    '丁三': {'p': 3}, '二四': {'p': 6, 'is_wild': True}, # 丁三牌及二四牌可以对调用
}

def create_full_deck():
    """
    根据定义的牌种和标准数量，生成一个包含32张牌的完整列表作为编码。
    """
    # 成对的牌
    double_tile_names = [
        '天', '地', '人', '和', '梅花', '长三', '板凳', 
        '斧头', '红头十', '高脚七', '零霖六'
    ]
    # 只有一张的牌
    single_tile_names = [
        '红九', '黑九', '平八', '斜八', '红七', '黑七', '红五', '黑五', '丁三', '二四'
    ]

    deck = []
    for name in double_tile_names:
        for _ in range(2):
            card_info = CARD[name].copy()
            card_info['name'] = name
            deck.append(card_info)
            
    for name in single_tile_names:
        card_info = CARD[name].copy()
        card_info['name'] = name
        deck.append(card_info)
        
    return deck

# 执行生成牌组编码
full_deck_encoding = create_full_deck()

# 将该编码使用excel保存
df = pd.DataFrame(full_deck_encoding)
df.to_excel("paijiu_encoding.xlsx", index=False, engine='openpyxl')
df.to_csv("paijiu_encoding.csv", index=False, encoding='utf-8-sig')
    

# 发牌程序
def distro_cards(deck, num_players=4, cards_per_hand=2):
    shuffled_deck = deck[:]
    random.shuffle(shuffled_deck)   # 打乱牌组顺序
    
    # 打乱牌组之后, 按照顺序分发给玩家
    player = []
    card_index = 0
    for i in range(num_players):
        hand = shuffled_deck[card_index : card_index + cards_per_hand]
        player.append(hand)
        card_index += cards_per_hand
        
    return player

# 比较与胜负判断
HAND_DEFINITIONS = [
    {'name': "至尊宝", 'cards': frozenset(['丁三', '二四'])},
    {'name': "双天", 'cards': frozenset(['天', '天'])},
    {'name': "双地", 'cards': frozenset(['地', '地'])},
    {'name': "孖人", 'cards': frozenset(['人', '人'])},
    {'name': "孖和", 'cards': frozenset(['和', '和'])},
    {'name': "孖梅", 'cards': frozenset(['梅花', '梅花'])},
    {'name': "孖长", 'cards': frozenset(['长三', '长三'])},
    {'name': "孖板凳", 'cards': frozenset(['板凳', '板凳'])},
    {'name': "孖斧头", 'cards': frozenset(['斧头', '斧头'])},
    {'name': "孖红头", 'cards': frozenset(['红头十', '红头十'])},
    {'name': "孖高脚", 'cards': frozenset(['高脚七', '高脚七'])},
    {'name': "孖零霖", 'cards': frozenset(['零霖六', '零霖六'])},
    {'name': "杂九对", 'cards': frozenset(['红九', '黑九'])},
    {'name': "杂八对", 'cards': frozenset(['平八', '斜八'])},
    {'name': "杂七对", 'cards': frozenset(['红七', '黑七'])},
    {'name': "杂五对", 'cards': frozenset(['红五', '黑五'])},
    {'name': "天王", 'cards': frozenset(['天', '红九'])},
    {'name': "天王", 'cards': frozenset(['天', '黑九'])},
    {'name': "地王", 'cards': frozenset(['地', '红九'])},
    {'name': "地王", 'cards': frozenset(['地', '黑九'])},
    {'name': "天牌八", 'cards': frozenset(['天', '平八'])},
    {'name': "天牌八", 'cards': frozenset(['天', '斜八'])},
    {'name': "地牌八", 'cards': frozenset(['地', '平八'])},
    {'name': "地牌八", 'cards': frozenset(['地', '斜八'])},
    {'name': "天高九", 'cards': frozenset(['天', '黑七'])},
    {'name': "地高九", 'cards': frozenset(['地', '高脚七'])}
]

# 您定义的对牌分数
PAIR_RANKING = {
    "至尊宝": 100, "双天": 99, "双地": 98, "孖人": 97, "孖和": 96,
    "孖梅": 95, "孖长": 94, "孖板凳": 93, "孖斧头": 92, "孖红头": 91,
    "孖高脚": 90, "孖零霖": 89, "杂九对": 88, "杂八对": 87,
    "杂七对": 86, "杂五对": 85, "天王": 84, "地王": 83, "天牌八": 82,
    "地牌八": 81, "天高九": 80, "地高九": 79
}

def evaluate_cards(hand):
    card1, card2 = hand[0], hand[1]
    card_names = frozenset([card1['name'], card2['name']])
    
    # 优先：查阅规则书，判断是否为特殊对牌
    for definition in HAND_DEFINITIONS:
        if card_names == definition['cards']:
            hand_name = definition['name']
            score = PAIR_RANKING.get(hand_name, 0)
            return (score, hand_name)
            
    # 其次：如果不是特殊对牌，则计算点数
    points = (card1['p'] + card2['p']) % 10
    
    # 仅当手中包含二四，且不与丁三成对时，此规则生效
    is_gee_joon = card_names == frozenset(['丁三', '二四'])
    if not is_gee_joon:
        # 检查是否有二四牌
        if card1.get('is_wild'): # '二四'
            # 计算二四当3点用时的分数
            wild_points = (3 + card2['p']) % 10
            # 取更优的结果
            if wild_points > points: points = wild_points
        elif card2.get('is_wild'): # '二四'
            wild_points = (card1['p'] + 3) % 10
            if wild_points > points: points = wild_points
            
    # 点数牌的分数是0-9，远小于特殊对牌的79-100分
    return (points, f"点数 {points}")

def run_game_round():
    
    # 创建并洗牌
    deck = create_full_deck()
    
    # 发牌给4位玩家
    player_hands = distro_cards(deck, num_players=4)
    
    # 评估每位玩家的手牌并储存结果
    evaluations = []
    for i, hand in enumerate(player_hands):
        hand_str = f"[{hand[0]['name']}, {hand[1]['name']}]"
        rank_score, rank_name = evaluate_cards(hand)
        evaluations.append({
            'player': i + 1, 
            'hand_str': hand_str, 
            'score': rank_score,
            'name': rank_name
        })
        print(f"玩家 {i+1} 的手牌: {hand_str:<20} -> 牌型: {rank_name}, 分数: {rank_score}")
    print("-" * 30)
    
    # 找出获胜者
    winner_info = max(evaluations, key=lambda x: x['score'])
    
    # 检查是否有平局
    max_score = winner_info['score']
    winners = [p for p in evaluations if p['score'] == max_score]
    
    # 宣布结果
    if len(winners) == 1:
        winner = winners[0]
        print(f"获胜者是: 玩家 {winner['player']}")
        print(f"手牌: {winner['hand_str']} ({winner['name']})")
    else:
        winner_players_str = ", ".join([f"玩家 {w['player']}" for w in winners])
        print(f"本轮为平局, 共同获胜者: {winner_players_str}")
        print(f"二者都以牌型“{winners[0]['name']}”获得最高分 {max_score}")

# --- 运行游戏 ---
if __name__ == "__main__":
    run_game_round()