游戏可以运行

This commit is contained in:
2026-05-24 08:39:26 +08:00
parent 035b2f7af9
commit ef564338a6
6 changed files with 522 additions and 143 deletions

View File

@@ -238,6 +238,63 @@ CARD_DATABASE = {
"description": "对敌方都城造成5伤害", "description": "对敌方都城造成5伤害",
"rarity": "legendary", "rarity": "legendary",
}, },
"qin_nuzhen": {
"id": "qin_nuzhen",
"name": "秦弩阵",
"faction": "qin",
"type": "unit",
"unit_type": "archer",
"cost": 3,
"op_cost": 1,
"attack": 2,
"defense": 2,
"max_hp": 3,
"description": "弓手·可从营地射击",
"abilities": ["ranged"],
"rarity": "common",
},
"qin_ruiqi": {
"id": "qin_ruiqi",
"name": "秦锐骑",
"faction": "qin",
"type": "unit",
"unit_type": "cavalry",
"cost": 3,
"op_cost": 1,
"attack": 3,
"defense": 2,
"max_hp": 2,
"description": "骑兵·冲锋",
"abilities": ["charge"],
"rarity": "common",
},
"qin_fangzhen": {
"id": "qin_fangzhen",
"name": "秦方阵",
"faction": "qin",
"type": "unit",
"unit_type": "infantry",
"cost": 2,
"op_cost": 1,
"attack": 2,
"defense": 3,
"max_hp": 3,
"description": "步兵·高防御",
"abilities": [],
"rarity": "common",
},
"qin_yuanjiao": {
"id": "qin_yuanjiao",
"name": "远交近攻",
"faction": "qin",
"type": "order",
"cost": 3,
"op_cost": 0,
"effect_type": "damage_hq",
"effect_params": {"damage": 3},
"description": "对敌方都城造成3伤害",
"rarity": "rare",
},
# ==================== 齐 (Qi) ==================== # ==================== 齐 (Qi) ====================
"qi_jiji": { "qi_jiji": {
@@ -348,6 +405,63 @@ CARD_DATABASE = {
"description": "所有友方单位+1/+1", "description": "所有友方单位+1/+1",
"rarity": "legendary", "rarity": "legendary",
}, },
"qi_changgong": {
"id": "qi_changgong",
"name": "齐长弓",
"faction": "qi",
"type": "unit",
"unit_type": "archer",
"cost": 2,
"op_cost": 1,
"attack": 2,
"defense": 2,
"max_hp": 2,
"description": "弓手·可从营地射击",
"abilities": ["ranged"],
"rarity": "common",
},
"qi_shangdui": {
"id": "qi_shangdui",
"name": "齐商队",
"faction": "qi",
"type": "unit",
"unit_type": "infantry",
"cost": 1,
"op_cost": 1,
"attack": 1,
"defense": 1,
"max_hp": 2,
"description": "部署时获得2粮草",
"abilities": ["gain_on_deploy:2"],
"rarity": "common",
},
"qi_maobing": {
"id": "qi_maobing",
"name": "齐矛兵",
"faction": "qi",
"type": "unit",
"unit_type": "infantry",
"cost": 3,
"op_cost": 1,
"attack": 3,
"defense": 3,
"max_hp": 3,
"description": "步兵",
"abilities": [],
"rarity": "common",
},
"qi_guanzhong": {
"id": "qi_guanzhong",
"name": "管仲治国",
"faction": "qi",
"type": "order",
"cost": 2,
"op_cost": 0,
"effect_type": "buff_all",
"effect_params": {"attack_bonus": 1, "defense_bonus": 1, "duration": 1},
"description": "所有友方单位+1/+1",
"rarity": "rare",
},
# ==================== 楚 (Chu) ==================== # ==================== 楚 (Chu) ====================
"chu_manbing": { "chu_manbing": {
@@ -458,6 +572,63 @@ CARD_DATABASE = {
"description": "召唤2个楚蛮兵到营地", "description": "召唤2个楚蛮兵到营地",
"rarity": "legendary", "rarity": "legendary",
}, },
"chu_manqi": {
"id": "chu_manqi",
"name": "楚蛮骑",
"faction": "chu",
"type": "unit",
"unit_type": "cavalry",
"cost": 3,
"op_cost": 1,
"attack": 3,
"defense": 2,
"max_hp": 2,
"description": "骑兵·冲锋",
"abilities": ["charge"],
"rarity": "common",
},
"chu_nushou": {
"id": "chu_nushou",
"name": "楚弩手",
"faction": "chu",
"type": "unit",
"unit_type": "archer",
"cost": 2,
"op_cost": 1,
"attack": 2,
"defense": 2,
"max_hp": 2,
"description": "弓手·可从营地射击",
"abilities": ["ranged"],
"rarity": "common",
},
"chu_wuzhu2": {
"id": "chu_wuzhu2",
"name": "楚巫祝",
"faction": "chu",
"type": "unit",
"unit_type": "infantry",
"cost": 2,
"op_cost": 1,
"attack": 1,
"defense": 2,
"max_hp": 3,
"description": "回合开始时恢复友方单位1HP",
"abilities": ["heal_all:1"],
"rarity": "common",
},
"chu_tianxian": {
"id": "chu_tianxian",
"name": "楚天险",
"faction": "chu",
"type": "order",
"cost": 3,
"op_cost": 0,
"effect_type": "heal_hq",
"effect_params": {"amount": 4},
"description": "恢复都城4HP",
"rarity": "rare",
},
# ==================== 燕 (Yan) ==================== # ==================== 燕 (Yan) ====================
"yan_qibing": { "yan_qibing": {
@@ -568,6 +739,75 @@ CARD_DATABASE = {
"description": "抽2牌", "description": "抽2牌",
"rarity": "rare", "rarity": "rare",
}, },
"yan_changqiang": {
"id": "yan_changqiang",
"name": "燕长枪",
"faction": "yan",
"type": "unit",
"unit_type": "infantry",
"cost": 2,
"op_cost": 1,
"attack": 2,
"defense": 3,
"max_hp": 3,
"description": "步兵·高防御",
"abilities": [],
"rarity": "common",
},
"yan_qingqi": {
"id": "yan_qingqi",
"name": "燕轻骑",
"faction": "yan",
"type": "unit",
"unit_type": "cavalry",
"cost": 3,
"op_cost": 0,
"attack": 3,
"defense": 1,
"max_hp": 2,
"description": "骑兵·冲锋·行动费用-1",
"abilities": ["charge"],
"rarity": "common",
},
"yan_chihou": {
"id": "yan_chihou",
"name": "燕斥候",
"faction": "yan",
"type": "unit",
"unit_type": "infantry",
"cost": 1,
"op_cost": 1,
"attack": 1,
"defense": 1,
"max_hp": 2,
"description": "部署时抽1牌",
"abilities": ["draw_on_deploy:1"],
"rarity": "common",
},
"yan_junling": {
"id": "yan_junling",
"name": "燕军令",
"faction": "yan",
"type": "order",
"cost": 2,
"op_cost": 0,
"effect_type": "buff_type",
"effect_params": {"unit_type": "cavalry", "attack_bonus": 1, "defense_bonus": 1, "duration": 1},
"description": "所有骑兵+1/+1",
"rarity": "rare",
},
"yan_danci": {
"id": "yan_danci",
"name": "燕丹刺秦",
"faction": "yan",
"type": "order",
"cost": 6,
"op_cost": 0,
"effect_type": "damage_hq",
"effect_params": {"damage": 6},
"description": "对敌方都城造成6伤害",
"rarity": "legendary",
},
# ==================== 韩 (Han) ==================== # ==================== 韩 (Han) ====================
"han_nubing": { "han_nubing": {
@@ -678,6 +918,63 @@ CARD_DATABASE = {
"description": "对敌方都城造成4伤害", "description": "对敌方都城造成4伤害",
"rarity": "legendary", "rarity": "legendary",
}, },
"han_changgong": {
"id": "han_changgong",
"name": "韩长弓",
"faction": "han",
"type": "unit",
"unit_type": "archer",
"cost": 3,
"op_cost": 1,
"attack": 2,
"defense": 3,
"max_hp": 3,
"description": "弓手·可从营地射击",
"abilities": ["ranged"],
"rarity": "common",
},
"han_tiejiang": {
"id": "han_tiejiang",
"name": "韩铁匠",
"faction": "han",
"type": "unit",
"unit_type": "infantry",
"cost": 1,
"op_cost": 1,
"attack": 1,
"defense": 1,
"max_hp": 2,
"description": "部署时获得2粮草",
"abilities": ["gain_on_deploy:2"],
"rarity": "common",
},
"han_fangzhen": {
"id": "han_fangzhen",
"name": "韩方阵",
"faction": "han",
"type": "unit",
"unit_type": "infantry",
"cost": 3,
"op_cost": 1,
"attack": 3,
"defense": 3,
"max_hp": 4,
"description": "步兵·高生命",
"abilities": [],
"rarity": "common",
},
"han_nuzhen": {
"id": "han_nuzhen",
"name": "韩弩阵",
"faction": "han",
"type": "order",
"cost": 3,
"op_cost": 0,
"effect_type": "damage_all_front",
"effect_params": {"damage": 2, "target": "enemy"},
"description": "对所有敌方前线单位造成2伤害",
"rarity": "rare",
},
# ==================== 赵 (Zhao) ==================== # ==================== 赵 (Zhao) ====================
"zhao_bianqi": { "zhao_bianqi": {
@@ -788,6 +1085,63 @@ CARD_DATABASE = {
"description": "一个友方单位+3/+3", "description": "一个友方单位+3/+3",
"rarity": "legendary", "rarity": "legendary",
}, },
"zhao_tieqi2": {
"id": "zhao_tieqi2",
"name": "赵轻骑",
"faction": "zhao",
"type": "unit",
"unit_type": "cavalry",
"cost": 4,
"op_cost": 1,
"attack": 4,
"defense": 2,
"max_hp": 3,
"description": "骑兵·冲锋",
"abilities": ["charge"],
"rarity": "common",
},
"zhao_gongshou2": {
"id": "zhao_gongshou2",
"name": "赵弓手",
"faction": "zhao",
"type": "unit",
"unit_type": "archer",
"cost": 2,
"op_cost": 1,
"attack": 2,
"defense": 2,
"max_hp": 2,
"description": "弓手·可从营地射击",
"abilities": ["ranged"],
"rarity": "common",
},
"zhao_qiangbing": {
"id": "zhao_qiangbing",
"name": "赵枪兵",
"faction": "zhao",
"type": "unit",
"unit_type": "infantry",
"cost": 2,
"op_cost": 1,
"attack": 2,
"defense": 3,
"max_hp": 3,
"description": "步兵·高防御",
"abilities": [],
"rarity": "common",
},
"zhao_junling": {
"id": "zhao_junling",
"name": "赵军令",
"faction": "zhao",
"type": "order",
"cost": 2,
"op_cost": 0,
"effect_type": "buff_all",
"effect_params": {"attack_bonus": 1, "defense_bonus": 0, "duration": 1},
"description": "所有友方单位+1攻击",
"rarity": "rare",
},
# ==================== 魏 (Wei) ==================== # ==================== 魏 (Wei) ====================
"wei_wuzu": { "wei_wuzu": {
@@ -898,50 +1252,63 @@ CARD_DATABASE = {
"description": "对所有敌方前线单位造成3伤害", "description": "对所有敌方前线单位造成3伤害",
"rarity": "legendary", "rarity": "legendary",
}, },
"wei_dunbing": {
# ==================== 中立牌 (Neutral) ==================== "id": "wei_dunbing",
"neutral_miliao": { "name": "魏盾兵",
"id": "neutral_miliao", "faction": "wei",
"name": "密探",
"faction": "neutral",
"type": "unit", "type": "unit",
"unit_type": "infantry", "unit_type": "infantry",
"cost": 1, "cost": 2,
"op_cost": 1, "op_cost": 1,
"attack": 1, "attack": 1,
"defense": 1, "defense": 3,
"max_hp": 2, "max_hp": 3,
"description": "部署时抽1牌", "description": "步兵·高防御",
"abilities": ["draw_on_deploy:1"],
"rarity": "common",
},
"neutral_yimin": {
"id": "neutral_yimin",
"name": "义民",
"faction": "neutral",
"type": "unit",
"unit_type": "infantry",
"cost": 1,
"op_cost": 1,
"attack": 1,
"defense": 2,
"max_hp": 2,
"description": "步兵",
"abilities": [], "abilities": [],
"rarity": "common", "rarity": "common",
}, },
"neutral_liangcao": { "wei_nushou": {
"id": "neutral_liangcao", "id": "wei_nushou",
"name": "粮草补给", "name": "魏弩手",
"faction": "neutral", "faction": "wei",
"type": "order", "type": "unit",
"cost": 0, "unit_type": "archer",
"op_cost": 0, "cost": 3,
"effect_type": "gain_provisions", "op_cost": 1,
"effect_params": {"amount": 2}, "attack": 2,
"description": "获得2粮草", "defense": 3,
"max_hp": 3,
"description": "弓手·可从营地射击",
"abilities": ["ranged"],
"rarity": "common", "rarity": "common",
}, },
"wei_zhancha": {
"id": "wei_zhancha",
"name": "魏战车",
"faction": "wei",
"type": "unit",
"unit_type": "chariot",
"cost": 5,
"op_cost": 2,
"attack": 4,
"defense": 4,
"max_hp": 4,
"description": "战车·无视报复",
"abilities": ["no_retaliation"],
"rarity": "common",
},
"wei_wuzuzhen": {
"id": "wei_wuzuzhen",
"name": "魏武卒阵",
"faction": "wei",
"type": "order",
"cost": 3,
"op_cost": 0,
"effect_type": "buff_type",
"effect_params": {"unit_type": "infantry", "attack_bonus": 2, "defense_bonus": 1, "duration": 1},
"description": "所有步兵+2/+1",
"rarity": "rare",
},
# ==================== 盟国 (Ally) ==================== # ==================== 盟国 (Ally) ====================
# --- 鲁 (Lu) --- # --- 鲁 (Lu) ---
@@ -1456,133 +1823,125 @@ DECK_PRESETS = {
"qin": { "qin": {
"faction": "qin", "faction": "qin",
"cards": [ "cards": [
"qin_tiesying", "qin_tiesying", "qin_tiesying", "qin_jiancu", "qin_jiancu", "qin_jiancu",
"qin_qiangnu", "qin_qiangnu", "qin_qiangnu",
"qin_bubing", "qin_bubing", "qin_bubing", "qin_bubing", "qin_bubing", "qin_bubing",
"qin_qibing", "qin_qibing", "qin_fangzhen", "qin_fangzhen", "qin_fangzhen",
"qin_gongcheng", "qin_gongcheng", "qin_qiangnu", "qin_qiangnu", "qin_qiangnu",
"qin_shangyang", "qin_shangyang", "qin_shangyang", "qin_shangyang",
"qin_lianheng", "qin_lianheng",
"qin_jiancu", "qin_jiancu", "qin_jiancu", "qin_nuzhen", "qin_nuzhen", "qin_nuzhen",
"qin_ruiqi", "qin_ruiqi", "qin_ruiqi",
"qin_tiesying", "qin_tiesying", "qin_tiesying",
"qin_yuanjiao", "qin_yuanjiao",
"qin_qibing", "qin_qibing",
"qin_gongcheng",
"qin_shihuang", "qin_shihuang",
"neutral_miliao", "neutral_miliao",
"neutral_yimin", "neutral_yimin", "neutral_yimin",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao",
"neutral_yimin",
"neutral_liangcao",
], ],
}, },
"qi": { "qi": {
"faction": "qi", "faction": "qi",
"cards": [ "cards": [
"qi_shangdui", "qi_shangdui", "qi_shangdui",
"qi_tongshang", "qi_tongshang", "qi_tongshang",
"qi_changgong", "qi_changgong", "qi_changgong",
"qi_guanzhong", "qi_guanzhong",
"qi_jiji", "qi_jiji", "qi_jiji", "qi_jiji", "qi_jiji", "qi_jiji",
"qi_shangren", "qi_shangren", "qi_shangren", "qi_shangren", "qi_shangren", "qi_shangren",
"qi_gongshou", "qi_gongshou", "qi_gongshou",
"qi_tianqi", "qi_tianqi",
"qi_tongshang", "qi_tongshang", "qi_tongshang",
"qi_jixia",
"qi_sunbin", "qi_sunbin", "qi_sunbin", "qi_sunbin",
"qi_gongshou", "qi_gongshou", "qi_gongshou",
"qi_jixia", "qi_jixia",
"qi_maobing", "qi_maobing", "qi_maobing",
"qi_fuguo", "qi_fuguo",
"neutral_miliao", "neutral_miliao", "qi_tianqi", "qi_tianqi",
"neutral_yimin", "neutral_yimin", "neutral_yimin",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao",
"neutral_yimin", "neutral_yimin",
"neutral_miliao",
"neutral_yimin",
], ],
}, },
"chu": { "chu": {
"faction": "chu", "faction": "chu",
"cards": [ "cards": [
"chu_manbing", "chu_manbing", "chu_manbing",
"chu_wuyi", "chu_wuyi", "chu_wuyi",
"chu_gongshou", "chu_gongshou", "chu_gongshou",
"chu_zhancha", "chu_zhancha",
"chu_gushou", "chu_gushou", "chu_gushou", "chu_gushou", "chu_gushou", "chu_gushou",
"chu_cici", "chu_nushou", "chu_nushou", "chu_nushou",
"chu_wuyi", "chu_wuyi", "chu_wuyi",
"chu_wuzhu2", "chu_wuzhu2", "chu_wuzhu2",
"chu_dazhao", "chu_dazhao", "chu_dazhao", "chu_dazhao",
"chu_gongshou", "chu_gongshou", "chu_gongshou",
"chu_manbing", "chu_manbing", "chu_manbing",
"chu_manqi", "chu_manqi", "chu_manqi",
"chu_tianxian", "chu_tianxian",
"chu_cici", "chu_cici",
"chu_zhancha", "chu_zhancha",
"chu_xiangyu", "chu_xiangyu",
"neutral_miliao", "neutral_miliao",
"neutral_yimin", "neutral_yimin", "neutral_yimin",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao",
"neutral_yimin", "neutral_yimin",
"neutral_miliao",
"neutral_yimin",
], ],
}, },
"yan": { "yan": {
"faction": "yan", "faction": "yan",
"cards": [ "cards": [
"yan_qibing", "yan_qibing", "yan_qibing", "yan_chihou", "yan_chihou", "yan_chihou",
"yan_cike", "yan_cike",
"yan_bubing", "yan_bubing", "yan_bubing",
"yan_gongshou", "yan_gongshou", "yan_gongshou",
"yan_jingke",
"yan_jixing", "yan_jixing", "yan_jixing", "yan_jixing", "yan_jixing", "yan_jixing",
"yan_bubing", "yan_bubing", "yan_bubing",
"yan_changqiang", "yan_changqiang", "yan_changqiang",
"yan_junling", "yan_junling",
"yan_qibing", "yan_qibing", "yan_qibing",
"yan_tuxi", "yan_tuxi", "yan_tuxi", "yan_tuxi",
"yan_yanzhao", "yan_yanzhao", "yan_cike", "yan_cike",
"neutral_yimin", "neutral_yimin", "neutral_yimin", "yan_gongshou", "yan_gongshou", "yan_gongshou",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao", "yan_qingqi", "yan_qingqi", "yan_qingqi",
"neutral_miliao", "neutral_miliao", "yan_yanzhao",
"neutral_miliao", "yan_jingke",
"neutral_yimin", "neutral_yimin", "yan_danci",
], ],
}, },
"han": { "han": {
"faction": "han", "faction": "han",
"cards": [ "cards": [
"han_tiejiang", "han_tiejiang", "han_tiejiang",
"han_liannu", "han_liannu", "han_liannu",
"han_nubing", "han_nubing", "han_nubing", "han_nubing", "han_nubing", "han_nubing",
"han_shushi", "han_shushi", "han_shushi", "han_shushi", "han_shushi", "han_shushi",
"han_jianbing", "han_jianbing", "han_jianbing",
"han_qibing", "han_qibing",
"han_weiwei", "han_weiwei", "han_weiwei", "han_weiwei",
"han_fubing", "han_changgong", "han_changgong", "han_changgong",
"han_liannu", "han_liannu", "han_liannu", "han_fangzhen", "han_fangzhen", "han_fangzhen",
"han_fubing", "han_fubing",
"han_jianbing", "han_jianbing", "han_jianbing",
"han_nuzhen", "han_nuzhen",
"han_qibing", "han_qibing",
"han_shenjian", "han_shenjian",
"neutral_miliao", "neutral_miliao",
"neutral_yimin", "neutral_yimin", "neutral_yimin",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao",
"neutral_yimin",
"neutral_miliao",
"neutral_yimin", "neutral_yimin",
], ],
}, },
"zhao": { "zhao": {
"faction": "zhao", "faction": "zhao",
"cards": [ "cards": [
"zhao_bianqi", "zhao_bianqi", "zhao_bianqi", "zhao_chongfeng", "zhao_chongfeng", "zhao_chongfeng",
"zhao_tieqi", "zhao_tieqi",
"zhao_bubing", "zhao_bubing", "zhao_bubing", "zhao_bubing", "zhao_bubing", "zhao_bubing",
"zhao_gongshou2", "zhao_gongshou2", "zhao_gongshou2",
"zhao_junling", "zhao_junling",
"zhao_qiangbing", "zhao_qiangbing", "zhao_qiangbing",
"zhao_qixi", "zhao_qixi",
"zhao_bianqi", "zhao_bianqi",
"zhao_gongshou", "zhao_gongshou", "zhao_gongshou", "zhao_gongshou", "zhao_gongshou", "zhao_gongshou",
"zhao_qixi", "zhao_qixi", "zhao_qixi", "zhao_wuling", "zhao_wuling",
"zhao_wuling",
"zhao_chongfeng", "zhao_chongfeng",
"zhao_lianpo", "zhao_lianpo",
"neutral_miliao", "neutral_miliao", "zhao_tieqi2", "zhao_tieqi2", "zhao_tieqi2",
"neutral_yimin", "neutral_yimin", "neutral_yimin", "zhao_tieqi",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao", "zhao_qixi",
"neutral_yimin", "neutral_yimin", "zhao_bianqi",
"neutral_miliao",
"neutral_yimin",
], ],
}, },
"wei": { "wei": {
"faction": "wei", "faction": "wei",
"cards": [ "cards": [
"wei_wuzu", "wei_wuzu", "wei_wuzu",
"wei_zhongzhuang", "wei_zhongzhuang", "wei_zhongzhuang",
"wei_gongshou", "wei_gongshou", "wei_gongshou",
"wei_qibing", "wei_qibing",
"wei_zhengjun", "wei_zhengjun", "wei_zhengjun",
"wei_diaodu", "wei_diaodu", "wei_diaodu", "wei_diaodu", "wei_diaodu", "wei_diaodu",
"wei_lianbao", "wei_dunbing", "wei_dunbing", "wei_dunbing",
"wei_gongshou", "wei_gongshou", "wei_gongshou",
"wei_zhengjun",
"wei_lianbao", "wei_lianbao",
"wei_nushou", "wei_nushou", "wei_nushou",
"wei_wuzu", "wei_wuzu", "wei_wuzu",
"wei_wuzuzhen", "wei_wuzuzhen",
"wei_zhongzhuang", "wei_zhongzhuang", "wei_zhongzhuang",
"wei_qibing", "wei_qibing", "wei_qibing",
"wei_zhancha", "wei_zhancha",
"wei_zhengjun",
"wei_weiliaozi", "wei_weiliaozi",
"neutral_miliao", "neutral_miliao",
"neutral_liangcao", "neutral_liangcao", "neutral_liangcao",
"neutral_yimin", "neutral_yimin", "neutral_yimin",
"neutral_yimin",
"neutral_miliao",
"neutral_yimin",
], ],
}, },
} }

View File

@@ -125,6 +125,12 @@ class Game:
self.ui.deck_builder_faction = self.player_faction self.ui.deck_builder_faction = self.player_faction
self.state = "deck_build" self.state = "deck_build"
return return
if "random" in self.ui.menu_buttons and self.ui.menu_buttons["random"].collidepoint(pos):
from card_game.config import FACTIONS
others = [f for f in FACTIONS.keys() if f != self.player_faction]
self.ai_faction = random.choice(others)
self._start_game()
return
fid = self.ui.get_faction_at(pos) fid = self.ui.get_faction_at(pos)
if fid and fid != self.player_faction: if fid and fid != self.player_faction:
self.ai_faction = fid self.ai_faction = fid

View File

@@ -186,6 +186,14 @@ class UI:
build_rect.centery - t.get_height() // 2)) build_rect.centery - t.get_height() // 2))
self.menu_buttons["deck_build"] = build_rect self.menu_buttons["deck_build"] = build_rect
# Random opponent button
random_rect = pygame.Rect(WINDOW_WIDTH // 2 - 80, WINDOW_HEIGHT - 60, 160, 40)
ink_style.draw_ink_rect(self.screen, random_rect, ZHU_HONG, alpha=200)
t = self.font_md.render("随机对手", True, PAPER_WHITE)
self.screen.blit(t, (random_rect.centerx - t.get_width() // 2,
random_rect.centery - t.get_height() // 2))
self.menu_buttons["random"] = random_rect
def draw_deck_builder(self, faction_id): def draw_deck_builder(self, faction_id):
from card_game.config import DECK_SIZE from card_game.config import DECK_SIZE
from collections import Counter from collections import Counter
@@ -203,7 +211,7 @@ class UI:
count_text = self.font_md.render(f"已选:{deck_count}/{DECK_SIZE}", True, count_color) count_text = self.font_md.render(f"已选:{deck_count}/{DECK_SIZE}", True, count_color)
self.screen.blit(count_text, (WINDOW_WIDTH // 2 - count_text.get_width() // 2, 42)) self.screen.blit(count_text, (WINDOW_WIDTH // 2 - count_text.get_width() // 2, 42))
# Left: available cards # Left: available cards (show stats inline)
self.deck_card_rects = [] self.deck_card_rects = []
left_x = 20 left_x = 20
left_y = 75 left_y = 75
@@ -211,15 +219,15 @@ class UI:
left_y += 25 left_y += 25
available = [c for c in CARD_DATABASE.values() available = [c for c in CARD_DATABASE.values()
if c["faction"] == faction_id or c["faction"] in ("neutral", "ally")] if c["faction"] == faction_id or c["faction"] == "ally"]
available.sort(key=lambda c: (c["cost"], c["name"])) available.sort(key=lambda c: (c["cost"], c["name"]))
small_w, small_h = 160, 32 small_w, small_h = 250, 42
cols = 4 cols = 2
for i, card_data in enumerate(available): for i, card_data in enumerate(available):
row, col = divmod(i, cols) row, col = divmod(i, cols)
x = left_x + col * (small_w + 8) x = left_x + col * (small_w + 6)
y = left_y + row * (small_h + 4) y = left_y + row * (small_h + 3)
if y + small_h > WINDOW_HEIGHT - 60: if y + small_h > WINDOW_HEIGHT - 60:
break break
cid = card_data["id"] cid = card_data["id"]
@@ -228,29 +236,33 @@ class UI:
can_add = in_deck < max_copies and deck_count < DECK_SIZE can_add = in_deck < max_copies and deck_count < DECK_SIZE
rect = pygame.Rect(x, y, small_w, small_h) rect = pygame.Rect(x, y, small_w, small_h)
if card_data["faction"] not in ("neutral", "ally"): if card_data["faction"] == faction_id:
bg = tuple(max(0, c - 30) for c in faction_color) bg = tuple(max(0, c - 30) for c in faction_color)
elif card_data["faction"] == "ally":
bg = (100, 90, 55)
else: else:
bg = (80, 75, 65) bg = (100, 90, 55)
ink_style.draw_ink_rect(self.screen, rect, bg, alpha=180) ink_style.draw_ink_rect(self.screen, rect, bg, alpha=180)
border_color = PAPER_WHITE if can_add else INK_WASH_3 border_color = PAPER_WHITE if can_add else INK_WASH_3
pygame.draw.rect(self.screen, border_color, rect, 1, border_radius=3) pygame.draw.rect(self.screen, border_color, rect, 1, border_radius=3)
# Line 1: cost + name + count
cost_s = self.font_sm.render(str(card_data["cost"]), True, TENG_HUANG) cost_s = self.font_sm.render(str(card_data["cost"]), True, TENG_HUANG)
self.screen.blit(cost_s, (x + 4, y + 8)) self.screen.blit(cost_s, (x + 4, y + 3))
icon = {"unit": "", "order": ""}.get(card_data["type"], "?") name_str = card_data["name"][:6]
ally_tag = card_data.get("ally_state", "") self.screen.blit(self.font_sm.render(name_str, True, PAPER_WHITE), (x + 22, y + 3))
if card_data["faction"] == "ally" and ally_tag:
icon = ally_tag
self.screen.blit(self.font_sm.render(icon, True, TENG_HUANG), (x + 22, y + 8))
self.screen.blit(self.font_sm.render(card_data["name"][:4], True, PAPER_WHITE), (x + 40, y + 8))
ct = f"×{in_deck}/{max_copies}" if in_deck > 0 else f"0/{max_copies}" ct = f"×{in_deck}/{max_copies}" if in_deck > 0 else f"0/{max_copies}"
cs = self.font_sm.render(ct, True, count_color if in_deck > 0 else GRAY) cs = self.font_sm.render(ct, True, count_color if in_deck > 0 else GRAY)
self.screen.blit(cs, (x + small_w - cs.get_width() - 4, y + 8)) self.screen.blit(cs, (x + small_w - cs.get_width() - 4, y + 3))
# Line 2: type + stats
if card_data["type"] == "unit":
icon = {"infantry": "", "cavalry": "", "chariot": "",
"archer": "", "siege": ""}.get(card_data.get("unit_type"), "?")
stats = f"{icon}{card_data['attack']}{card_data['defense']}{card_data['max_hp']}"
else:
stats = f"谋略: {card_data['description'][:12]}"
self.screen.blit(self.font_sm.render(stats, True, LIGHT_GRAY), (x + 22, y + 22))
self.deck_card_rects.append((rect, cid)) self.deck_card_rects.append((rect, cid))
# Right: current deck # Right: current deck
@@ -265,30 +277,32 @@ class UI:
for i, (cid, count) in enumerate(deck_items): for i, (cid, count) in enumerate(deck_items):
card_data = CARD_DATABASE[cid] card_data = CARD_DATABASE[cid]
row, col = divmod(i, 3) row, col = divmod(i, 2)
x = right_x + col * (small_w + 8) x = right_x + col * (small_w + 6)
y = right_y + row * (small_h + 4) y = right_y + row * (small_h + 3)
if y + small_h > WINDOW_HEIGHT - 60: if y + small_h > WINDOW_HEIGHT - 60:
break break
rect = pygame.Rect(x, y, small_w, small_h) rect = pygame.Rect(x, y, small_w, small_h)
if card_data["faction"] not in ("neutral", "ally"): if card_data["faction"] == faction_id:
bg = tuple(max(0, c - 30) for c in faction_color) bg = tuple(max(0, c - 30) for c in faction_color)
elif card_data["faction"] == "ally":
bg = (100, 90, 55)
else: else:
bg = (80, 75, 65) bg = (100, 90, 55)
ink_style.draw_ink_rect(self.screen, rect, bg, alpha=180) ink_style.draw_ink_rect(self.screen, rect, bg, alpha=180)
pygame.draw.rect(self.screen, GOLD, rect, 1, border_radius=3) pygame.draw.rect(self.screen, GOLD, rect, 1, border_radius=3)
self.screen.blit(self.font_sm.render(str(card_data["cost"]), True, TENG_HUANG), (x + 4, y + 8)) self.screen.blit(self.font_sm.render(str(card_data["cost"]), True, TENG_HUANG), (x + 4, y + 3))
icon = {"unit": "", "order": ""}.get(card_data["type"], "?") name_str = card_data["name"][:6]
ally_tag = card_data.get("ally_state", "") self.screen.blit(self.font_sm.render(name_str, True, PAPER_WHITE), (x + 22, y + 3))
if card_data["faction"] == "ally" and ally_tag:
icon = ally_tag
self.screen.blit(self.font_sm.render(icon, True, TENG_HUANG), (x + 22, y + 8))
self.screen.blit(self.font_sm.render(card_data["name"][:4], True, PAPER_WHITE), (x + 40, y + 8))
cs = self.font_sm.render(f"×{count}", True, SONGHUA_GREEN) cs = self.font_sm.render(f"×{count}", True, SONGHUA_GREEN)
self.screen.blit(cs, (x + small_w - cs.get_width() - 4, y + 8)) self.screen.blit(cs, (x + small_w - cs.get_width() - 4, y + 3))
if card_data["type"] == "unit":
icon = {"infantry": "", "cavalry": "", "chariot": "",
"archer": "", "siege": ""}.get(card_data.get("unit_type"), "?")
stats = f"{icon}{card_data['attack']}{card_data['defense']}{card_data['max_hp']}"
else:
stats = f"谋略: {card_data['description'][:12]}"
self.screen.blit(self.font_sm.render(stats, True, LIGHT_GRAY), (x + 22, y + 22))
self.deck_build_rects.append((rect, cid)) self.deck_build_rects.append((rect, cid))
# Bottom buttons # Bottom buttons