kards-env/README.md

19 KiB
Raw Blame History

KARDS 战斗系统

一个基于Python的KARDS二战卡牌游戏战斗系统复刻采用可扩展的架构设计。

📋 最新更新 (2025-09-04) - v0.3.0

🎴 卡牌系统重大升级:

  • 模板继承系统: 卡牌定义支持模板继承,大幅减少代码重复
  • 参数化卡牌: 完整的卡牌参数系统,支持部署位置选择等交互
  • 多国卡牌支持: 德国、意大利、美国、日本卡牌全面实现
  • YAML加载器: 强化的YAML加载器支持模板合并和验证

🔧 模板系统特性:

  • unit_card 模板提供标准的 deploy_position 参数
  • 卡牌只需 template: "unit_card" 而无需重复配置
  • 模板参数继承和合并机制
  • 所有单位卡自动支持部署到己方支援线的可选位置选择

📚 项目文档完善:

  • 完整的卡牌系统架构文档
  • 模板继承系统使用指南
  • 参数系统开发者文档
  • 代码示例和最佳实践

🏗️ 项目重构完成 (v0.2.0):

  • 完整的pytest测试套件19个测试100%通过)
  • 玩家API优化使用整数ID (0/1) 替代字符串
  • 代码结构优化:封存旧版本,清理项目结构
  • uv环境管理标准化依赖和虚拟环境

🎯 项目目标

  • 复刻KARDS游戏的核心战斗机制
  • 为AI Agent提供完整的游戏环境
  • 可扩展的单位、能力和效果系统

核心特性

🏗️ 战场系统

  • 三线战场: 玩家1支援线 - 共用前线 - 玩家2支援线
  • HQ系统: 总部作为支援线上的目标20点防御值摧毁敌方HQ获胜
  • 紧凑排列: 单位自动紧凑排列,无空隙
  • 前线控制权: 当前线被单一玩家控制时获得控制权
  • 目标限制: 每条战线最多5个目标包括单位和HQ

🚗 单位类型

类型 英文名 攻击规则 特殊能力
步兵 INFANTRY 只能攻击相邻战线 基础作战单位
坦克 TANK 只能攻击相邻战线 可同回合移动+攻击
火炮 ARTILLERY 无视攻击距离无视守护 不受反击
战斗机 FIGHTER 无视攻击距离 保护同战线免受轰炸机攻击
轰炸机 BOMBER 无视攻击距离无视守护 不受反击(战斗机除外),但会被战斗机阻挡

🎯 关键词系统

  • BLITZ (闪击): 部署回合可立即行动
  • GUARD (守护): 相邻单位只能被轰炸机/火炮攻击
  • SMOKESCREEN (烟幕): 不能被攻击,行动后失效
  • HEAVY_ARMOR_X (重甲): 受到伤害减少X点
  • AMBUSH (伏击): 首次被攻击时先造成伤害
  • FURY (奋战): 每回合可攻击两次
  • MOBILIZE (动员): 回合开始+1/+1受伤后失效
  • PINNED (压制): 无法移动或攻击

🎪 能力系统

  • 部署能力 (Deploy): 进场时触发
  • 触发能力 (Triggered): 特定条件下触发
  • 静态能力 (Static): 持续生效的光环效果
  • 激活能力 (Activated): 主动使用的能力
  • 死亡能力 (Death): 被摧毁时触发

🎴 卡牌系统

核心特性

  • 模板继承系统: 减少重复定义,提高维护性
  • 参数化交互: 卡牌支持复杂的参数化操作
  • 多国卡牌: 完整支持德国、意大利、美国、日本等国家
  • YAML驱动: 所有卡牌定义通过YAML文件管理
  • 类型安全: 完整的参数验证和类型检查

🏗️ 模板继承系统

卡牌模板系统允许卡牌继承通用配置,避免重复定义:

# 模板定义 (cards_spec.yaml)
card_templates:
  - id: "unit_card"
    type: "unit"
    params:
      - name: "deploy_position"
        type: "slot"
        range: [0, 4]
        required: false
        description: "Deploy position (0-4, default: rightmost available slot)"

# 使用模板的卡牌 (japan.yaml)
unit_cards:
  - id: "jpn_imperial_guard_card"
    template: "unit_card"  # 继承模板配置
    name: "Imperial Guard"
    cost: 3
    nation: "japan"
    rarity: 4
    description: "Elite Japanese Imperial Guard infantry"
    unit_definition_id: "jpn_infantry_imperial_guard"

模板系统优势:

  • 减少90%+重复代码: 单位卡无需重复定义部署参数
  • 统一标准化: 所有单位卡自动获得标准参数
  • 易于维护: 修改模板即可影响所有继承卡牌
  • 灵活扩展: 支持多层继承和参数合并

📋 参数系统

卡牌参数系统支持复杂的玩家交互:

from kards_battle.cards.card_params import ParameterType, ParameterDefinition

# 部署位置参数
position_param = ParameterDefinition(
    name="deploy_position",
    param_type=ParameterType.SLOT,
    param_range=(0, 4),
    required=False,
    description="选择部署位置 (0-4)"
)

支持的参数类型:

  • SLOT: 位置选择 (0-4)
  • UNIT_TARGET: 单位目标选择
  • MULTI_TARGET: 多目标选择
  • CHOICE: 选项选择
  • BOOLEAN: 布尔选择

🌍 多国卡牌支持

目前支持的国家及卡牌数量:

国家 卡牌文件 卡牌数量 特色单位
🇩🇪 德国 germany.yaml 15+ 豹式坦克、Bf 109战斗机
🇮🇹 意大利 italy.yaml 12+ M13坦克、精英步兵
🇺🇸 美国 usa.yaml 18+ 谢尔曼坦克、P-51野马
🇯🇵 日本 japan.yaml 23+ 九七式坦克、零式战斗机

📖 卡牌加载器 API

from kards_battle.cards.card_loader import CardLoader, load_nation_cards
from kards_battle.core.enums import Nation

# 创建加载器
loader = CardLoader()

# 加载指定国家卡牌
japan_cards = loader.load_nation_cards(Nation.JAPAN)
print(f"加载了 {len(japan_cards)} 张日本卡牌")

# 加载所有可用卡牌
all_cards = loader.load_all_available_cards()
for nation, cards in all_cards.items():
    print(f"{nation.name}: {len(cards)} 张卡牌")

# 便捷函数
cards = load_nation_cards(Nation.GERMANY)

🎯 卡牌定义格式

单位卡完整格式:

unit_cards:
  - id: "unique_card_id"           # 必需:唯一标识符
    template: "unit_card"          # 可选:继承模板
    name: "Card Name"              # 必需:卡牌名称
    cost: 3                        # 必需:费用
    nation: "germany"              # 必需:国家
    rarity: 2                      # 必需:稀有度 (1-4)
    description: "Card description" # 可选:描述
    unit_definition_id: "unit_id"  # 必需:对应单位定义
    
    # 可选参数(如果不使用模板)
    params:
      - name: "deploy_position"
        type: "slot"
        range: [0, 4]
        required: false

📁 项目结构

项目根目录/
├── run_tests.sh              # 测试运行脚本
├── README.md                 # 项目文档
├── demo/                     # 演示文件目录
│   ├── demo_new_features.py  # 最新功能专项演示
│   ├── demo_card_system.py   # 卡牌系统演示
│   ├── demo_parameterized_cards.py # 参数化卡牌演示
│   ├── main.py               # 主入口文件
│   └── DEMOS.md              # 演示文件说明
│
├── examples/                 # 完整示例目录 🆕
│   └── card_system/          # 卡牌系统示例
│       ├── demo_card_system.py      # 卡牌加载和使用示例
│       └── demo_parameterized_cards.py # 参数化卡牌示例
│
├── assets/                   # 游戏资源文件 🆕
│   ├── cards/                # 卡牌定义文件
│   │   ├── cards_spec.yaml   # 卡牌格式规范和模板定义
│   │   ├── germany.yaml      # 德国卡牌 (15+ 张)
│   │   ├── italy.yaml        # 意大利卡牌 (12+ 张)
│   │   ├── usa.yaml          # 美国卡牌 (18+ 张)
│   │   ├── japan.yaml        # 日本卡牌 (23+ 张) 🆕
│   │   └── example_orders.yaml # 示例指令卡
│   └── units/                # 单位定义文件
│       ├── units_spec.yaml   # 单位格式规范
│       ├── germany.yaml      # 德国单位
│       ├── usa.yaml          # 美国单位
│       └── japan.yaml        # 日本单位 🆕
│
├── kards_battle/             # 核心战斗系统包
│   ├── core/                 # 核心引擎和逻辑
│   │   ├── battle_engine.py  # 新战斗引擎
│   │   ├── enums.py         # 枚举定义 (单位类型、战线等)
│   │   └── unit_combat_rules.py # 单位战斗规则
│   ├── cards/               # 卡牌系统 🆕
│   │   ├── card.py          # 卡牌基类和单位卡实现
│   │   ├── card_loader.py   # YAML卡牌加载器 (支持模板继承)
│   │   ├── card_params.py   # 卡牌参数系统
│   │   ├── card_manager.py  # 卡牌管理器
│   │   ├── deck.py          # 卡组管理
│   │   └── placeholder_cards.py # 占位卡牌定义
│   ├── units/               # 单位系统
│   │   ├── unit.py          # 单位基类和实现
│   │   └── unit_loader.py   # 单位加载器
│   ├── game/                # 游戏引擎和状态管理
│   │   ├── game_engine.py   # 高级游戏引擎
│   │   ├── game_state.py    # 游戏状态管理
│   │   └── nation_config.py # 国家配置
│   ├── battlefield/         # 战场管理
│   │   └── battlefield.py   # 基础战场系统
│   ├── abilities/           # 能力和关键词系统
│   │   ├── abilities.py     # 能力基类和接口
│   │   └── keywords.py      # 关键词效果实现
│   ├── effects/            # 效果系统
│   │   ├── effects.py      # 游戏效果实现
│   │   └── target_selectors.py # 目标选择逻辑
│   ├── events/             # 事件系统
│   │   ├── event_system.py # 事件分发器
│   │   └── managers/       # 事件管理器
│   └── examples/           # 示例单位和演示
│       └── sample_units.py # 15个示例单位定义
│
├── interactive/             # 交互式功能 
│   ├── battle_visualizer.py # 战场可视化器
│   ├── command_parser.py    # 命令解析器  
│   ├── interactive_test.py  # 交互测试
│   └── test_scenarios.py   # 测试场景
│
├── docs/                   # 项目文档
│   ├── KARDS_GAME_RULES.md # 游戏规则说明
│   ├── TESTING.md         # 测试说明
│   └── architecture/      # 架构文档
│       └── SYSTEM_DESIGN.md # 系统设计文档
│
└── tests/                  # 完整测试套件
    ├── test_card_loader.py      # 卡牌加载器测试 🆕
    ├── test_card_params.py      # 卡牌参数系统测试 🆕
    ├── test_card_system.py      # 卡牌系统集成测试 🆕
    ├── unit/                    # 单元测试
    ├── integration/             # 集成测试
    ├── examples/               # 示例和用法测试
    └── README.md              # 测试说明文档

🚀 快速开始

真实的KARDS操作体验

from kards_battle.core.battle_engine import BattleEngine
from kards_battle.examples.sample_units import create_american_gi, create_german_infantry
from kards_battle.core.enums import LineType

# 创建战斗引擎 (专注战斗系统,不包含卡牌)
engine = BattleEngine("Germany", "USA", debug_mode=True)

# 创建单位并设置激活成本
german_infantry = create_german_infantry()
american_gi = create_american_gi()
german_infantry.activation_cost = 1
american_gi.activation_cost = 1

print(f"初始状态:")
print(f"德军 - Kredits: {engine.get_kredits('Germany')}, Slot: {engine.get_kredits_slot('Germany')}")
print(f"美军 - Kredits: {engine.get_kredits('USA')}, Slot: {engine.get_kredits_slot('USA')}")

# 第1回合 - 德军直接部署单位到支援线
result1 = engine.deploy_unit_to_support(german_infantry, "Germany")
print(f"德军步兵部署到支援线: {result1['success']}")

# 切换到美军回合 (Kredits Slot自动增长)
engine.end_turn()
print(f"美军回合 - Kredits: {engine.get_kredits('USA')}, Slot: {engine.get_kredits_slot('USA')}")

# 第2回合 - 美军部署并移动
result2 = engine.deploy_unit_to_support(american_gi, "USA")
print(f"美军GI部署到支援线: {result2['success']}")

# 美军移动GI到前线 (消耗1点Kredits激活费用)
move_result = engine.move_unit(american_gi.id, (LineType.FRONT, 0), "USA")
print(f"美军GI移动到前线: {move_result['success']}")
if move_result['success']:
    print(f"前线控制权: {move_result['front_line_controller']}")

print(f"美军剩余Kredits: {engine.get_kredits('USA')}")

# 第3回合 - 德军反击
engine.end_turn()
print(f"德军回合 - Kredits: {engine.get_kredits('Germany')}")

# 德军从支援线攻击前线的美军 (消耗1点Kredits激活费用)
attack_result = engine.attack_target(german_infantry.id, american_gi.id, "Germany")
print(f"德军攻击美军: {attack_result['success']}")
if attack_result['success']:
    print(f"造成伤害: {attack_result['damage_dealt']}, 反击伤害: {attack_result['counter_damage']}")

# 查看最终战场状态
print(f"\n最终战场:")
print(engine.battlefield)

# DEBUG功能演示 - 设置资源和属性
engine.debug_set_kredits("Germany", kredits=10)
engine.debug_set_unit_stats(german_infantry.id, attack=5, defense=8)
print(f"\nDEBUG: 德军Kredits设为10步兵属性增强为 5/8")

运行演示

# 最新功能演示 (推荐先运行)
python3 demo/demo_new_features.py

# 主程序入口
python3 demo/main.py

运行测试

# 🧪 运行pytest测试套件推荐
./run_pytest.sh                                    # 运行所有pytest测试19个

# 或分别运行
uv run pytest tests/test_comprehensive_movement.py -v  # 移动系统测试10个
uv run pytest tests/test_turn_and_resources.py -v      # 回合资源测试9个

# 🔧 运行传统测试套件
./run_tests.sh                                     # 旧版测试运行器

# 特定测试类别
python3 tests/unit/test_battle_engine.py           # 新战斗引擎测试
python3 tests/unit/test_unit_type_rules.py         # 单位类型规则测试
python3 tests/integration/test_system.py          # 系统集成测试

推荐使用pytest套件 - 覆盖所有核心功能的完整验证!

🔧 扩展系统

创建自定义单位

from kards_battle.units.unit import Unit
from kards_battle.core.enums import UnitType

# 创建基础单位
custom_unit = Unit(
    name="Custom Tank",
    unit_type=UnitType.TANK,
    attack=4,
    defense=5,
    operation_cost=4,
    keywords={"BLITZ", "HEAVY_ARMOR_1"}
)

创建自定义能力

from kards_battle.abilities.abilities import DeployAbility

class CustomDeployAbility(DeployAbility):
    def get_valid_targets(self, owner, battlefield):
        # 实现目标选择逻辑
        return []
    
    def execute(self, owner, battlefield, target=None, context=None):
        # 实现能力效果
        return {"success": True}

创建自定义关键词

from kards_battle.abilities.keywords import KeywordEffect, TriggerTiming

class CustomKeyword(KeywordEffect):
    def get_trigger_timing(self):
        return [TriggerTiming.ON_DEPLOY]
    
    def _execute_effect(self, owner, battlefield, timing, context):
        # 实现关键词效果
        pass

📊 示例单位

系统包含15个示例单位展示各种能力组合

德军:

  • Panzer IV (闪击坦克)
  • Panther Tank (重甲坦克)
  • Bf 109 (伏击战斗机)
  • Ju 87 Stuka (轰炸机)
  • German 88mm Gun (部署伤害火炮)

美军:

  • M4 Sherman (闪击坦克)
  • P-51 Mustang (奋战战斗机)
  • B-17 Flying Fortress (重型轰炸机)
  • Field Officer (增益光环)

特殊单位:

  • Elite Sniper (烟幕+动员)

  • Combat Medic (死亡治疗)

  • Kamikaze Pilot (牺牲攻击)

🔄 游戏流程

  1. 玩家回合: 可自由进行以下操作
    • 直接部署单位到己方支援线(不需要卡牌)
    • 移动单位支援线→前线消耗Kredits激活费用
    • 攻击敌方目标消耗Kredits激活费用
  2. 回合结束: 切换玩家Kredits Slot自动增长Kredits重置为Slot数值
  3. 胜利条件: 摧毁敌方HQ20→0防御值

💰 Kredits资源系统

  • Kredits Slot: 每回合自增1上限12代表"钱包容量"
  • Kredits: 每回合重置为Slot数值当前可用"资源"
  • 激活费用: 移动和攻击都需要消耗单位的activation_cost点Kredits

🎮 核心操作机制

  • 直接部署: deploy_unit_to_support() - 将单位部署到己方支援线
  • 移动单位: move_unit() - 从支援线移动到前线(包括挤位置)
  • 攻击目标: attack_target() - 攻击敌方单位或HQ
  • DEBUG功能: 调试模式下可直接编辑单位属性和玩家资源

🧪 测试结果

系统通过了以下测试:

纯战斗系统: 专注战斗机制,不包含卡牌系统 🆕
Kredits资源系统: Kredits Slot/Kredits双层资源管理 🆕
直接单位部署: 函数调用直接部署到支援线 🆕
DEBUG功能系统: 完整的调试和编辑功能 🆕
真实的3条战线布局
HQ作为支援线上的目标
单位自动紧凑排列
前线控制权动态更新
前线内挤位置机制
跨线攻击规则
完整的单位类型战斗规则 🆕
火炮和轰炸机不受反击
轰炸机被战斗机保护机制
关键词效果触发 (伏击、重甲等)
战斗伤害计算和反击
游戏状态管理

🎯 后续扩展方向

  • AI对手实现
  • 完整的卡牌系统
  • 资源管理系统
  • 图形用户界面
  • 网络对战功能
  • 更多单位和能力
  • 保存/加载游戏
  • 战斗回放系统

🏆 设计亮点

真实战场还原

  • 3条战线布局: 完全符合KARDS真实游戏规则
  • 紧凑排列机制: 单位自动填补空隙,无碎片化
  • 前线控制权: 动态计算和更新控制权状态
  • HQ作为目标: 总部正确放置在支援线上

可扩展架构

  • 组件模式: 单位通过组合关键词和能力构建
  • 策略模式: 不同能力实现为独立策略类
  • 事件驱动: 所有游戏逻辑通过事件触发
  • 工厂模式: 关键词和效果可动态创建

高度模块化

  • 核心系统与具体内容分离
  • 每个模块职责单一,低耦合
  • 便于单独测试和扩展

真实游戏机制

  • 完整复现KARDS核心规则
  • 准确的单位类型和特殊规则
  • 详细的关键词效果实现

基于KARDS: The WWII Card Game设计用于学习和AI研究目的