Skip to content

Latest commit

 

History

History
336 lines (271 loc) · 9.92 KB

File metadata and controls

336 lines (271 loc) · 9.92 KB

Gwent TTS - 昆特牌 Tabletop Simulator 实现

一个基于 Tabletop Simulator (TTS) 平台的昆特牌(Gwent)游戏实现,采用 Python 后端 + Lua 前端的双层架构,支持自定义卡牌脚本编译和事件驱动的游戏逻辑。

📋 项目概述

本项目实现了完整的昆特牌双人对局系统,包括:

  • GwentScript 编译器:将自定义的 GC 语法编译为 Python 代码
  • Python 后端服务器:处理游戏逻辑、事件分发和卡牌效果
  • TTS Lua 客户端:负责游戏界面、交互和视觉效果
  • 完整的事件系统:支持 Deploy、Order、RoundEnd 等多种事件类型

✨ 已实现功能

🎮 核心游戏流程

1. 完整对局流程

  • 初始发牌:双方各发10张手牌
  • 换牌阶段:支持重新调度手牌(Redeal)
  • 回合制对战:交替出牌,支持Pass机制
  • 回合结算:自动计算战力、判定胜负
  • 三局两胜:完整的Bo3对局流程
  • 墓场管理:回合结束时卡牌自动移入墓场

2. 区域系统

  • 近战排(Melee):双方各有近战区域
  • 远程排(Range):双方各有远程区域
  • 墓场(Grave):已使用卡牌的归宿
  • 牌库(Deck):未抽到的卡牌
  • 手牌区(Hand):玩家手中的卡牌

🃏 卡牌系统

1. 卡牌类型支持

  • 单位卡(Unit):具有战力的基础卡牌
  • 谋略卡(Stratagem):开局自动部署的特殊卡
  • 能力卡(Ability):提供被动效果的卡牌
  • 领袖卡(Leader):玩家领袖(待完善)

2. 卡牌属性

  • 战力(Power):基础战力和当前战力
  • 护甲(Armor):吸收伤害的护盾
  • 人口(Provision):卡组构建限制
  • 阵营(Faction):卡牌所属阵营
  • 稀有度(Rarity):金/银/铜/特殊
  • 颜色(Color):紫色/黄色(玩家标识)

3. 状态Token系统

  • 护甲标记:显示剩余护甲值
  • 充能标记:显示可用次数
  • 状态标记:坚韧、免疫、锁定等(框架已搭建)

⚡ 事件系统

1. 已实现的事件类型

  • Deploy:卡牌部署到战场时触发
  • Order:玩家点击Order按钮时触发(异步支持)
  • RoundEnd:回合结束时触发
  • TurnStart:回合开始时触发(框架已搭建)
  • DamageReceived:受到伤害时触发(框架已搭建)

2. 事件过滤机制

  • 自身过滤[self] - 仅响应自身触发的事件
  • 友方过滤[ally] - 仅响应友方触发的事件
  • 敌方过滤[enemy] - 仅响应敌方触发的事件
  • 名称过滤[name('卡牌名')] - 特定名称的卡牌
  • 标签过滤[tag('标签')] - 具有特定标签的卡牌

🔧 ServerUtils API

1. 卡牌操作方法

# 增益/减益
card.boost(amount)        # 增加战力
card.damage(amount)       # 造成伤害
card.heal(amount)         # 治疗(移除伤害)

# 位置判断
card.onBattleGround()     # 是否在战场上
card.inGrave()            # 是否在墓场
card.inDeck()             # 是否在牌库

# 位置移动
card.jumpTo(target)       # 移动到指定区域
# target: "allyRows", "enemyRows", "battleGround", 或具体坐标

2. 选择机制

# 异步选择目标
target = await card.choose(conditions, type)
# conditions: allyRows, enemyRows, battleGround
# type: "unit", "stratagem" 等卡牌类型

3. 辅助函数

# 事件过滤
filter_event(event, conditions, self_ref)

# 列表过滤
filter_list(list_to_filter, conditions)

# 生成卡牌
spawn(card_name)          # 通过名称生成卡牌
play(card)                # 打出卡牌到战场

# 工具函数
name(card_name)           # 创建名称过滤器
tag(tag_name)             # 创建标签过滤器
getname(dataId)           # 获取卡牌名称
gettags(dataId)           # 获取卡牌标签

🎯 Order能力系统

1. 完整流程

  • 按钮创建:Deploy后自动添加Order按钮
  • 按钮点击:玩家点击触发Order事件
  • 异步执行:支持async/await异步操作
  • 目标选择:Order中可使用choose选择目标
  • 按钮移除:使用后可调用remove_button()移除

2. 示例代码

async def Order1(event):
    if not filter_event(event, [], self_reference):
        return
    target = await choose(allyRows, "unit")
    target.boost(1)

🔄 RoundEnd回合结算

1. 触发时机

  • ✅ 双方都Pass后触发
  • ✅ 在卡牌移入墓场之前触发
  • ✅ 卡牌仍在战场上,可正确判断位置

2. 示例应用

def RoundEnd1(event):
    if not filter_event(event, [self_reference], self_reference):
        return
    
    if self_reference.onBattleGround():
        self_reference.boost(1)  # 回合结束增益

🛠️ GwentScript 编译器

1. 编译流程

GC源代码 (.txt) 
    ↓ [Lexer + Parser]
AST抽象语法树 (JSON)
    ↓ [ASTToPython.py]
Python代码 (.py)
    ↓ [Import]
运行时加载

2. 支持的GC语法

  • 事件订阅Deploy[self], Order[self], RoundEnd[self]
  • 条件判断?, ?!, ! (if/else)
  • 循环语句for list as var
  • 赋值运算=, +=, -=, *=, /=
  • 选择机制choose num from place where filter as var
  • 函数调用boost(), damage(), jumpTo()

3. 示例GC代码

Deploy[self]
    boost(2)

RoundEnd[self]
    onBattleGround()?
        boost(1)

🌐 前后端通信

1. 通信协议

  • HTTP POST:事件发送到后端
  • JSON格式:结构化数据传输
  • Action系统:后端指令前端执行操作

2. Action类型

  • power:修改卡牌战力
  • heal:治疗卡牌
  • jumpTo:移动卡牌位置
  • choose:显示选择界面
  • addButton:添加交互按钮
  • removeButton:移除交互按钮
  • spawnCard:生成新卡牌

📊 数据管理

1. 卡牌数据库

  • database.json:存储所有卡牌元数据
  • 名称映射:多语言支持(中文)
  • 标签系统:卡牌分类和过滤
  • 属性定义:战力、护甲、人口等

2. 游戏状态

  • GameInfo对象:完整的游戏状态快照
  • 实时同步:每次事件发送最新状态
  • 序列化支持:pickle/json格式存储

📁 项目结构

Gwent-TTS/
├── code.lua                 # TTS Lua主脚本
├── HostTest.py              # Flask后端服务器
├── GameServer.py            # 游戏服务器核心逻辑
├── ServerUtils.py           # 卡牌操作API
├── ASTToPython.py           # GC编译器
├── lexer.py                 # 词法分析器
├── parser.py                # 语法分析器
│
├── GCodesOriginal/          # GC源代码目录
│   ├── card201727.txt
│   └── card201728.txt
│
├── GCodes/                  # 编译后的Python代码
│   ├── card201727.py
│   ├── card201728.py
│   └── 122316.py
│
├── assets/
│   └── data/
│       └── database.json    # 卡牌数据库
│
├── schema/                  # JSON Schema定义
├── key/                     # SSL证书
├── templates/               # HTML模板
│
├── ROADMAP.md               # 开发路线图
├── ROUND_END_TEST.md        # RoundEnd测试文档
├── ORDER_TEST.md            # Order能力测试文档
├── 里程碑1.3完成总结.md
└── 里程碑1.4完成总结.md

🚀 快速开始

环境要求

  • Python 3.8+
  • Tabletop Simulator(Steam)
  • Flask + Hypercorn

安装依赖

pip install flask hypercorn asyncio

启动后端

python HostTest.py

加载TTS脚本

  1. 在TTS中创建游戏桌
  2. 打开脚本编辑器(Scripting → Editor)
  3. 粘贴 code.lua 的内容
  4. 保存并运行

编译卡牌

python ASTToPython.py GCodesOriginal/card201727.txt

📖 开发文档

核心文档

技术架构

  • 前端:Tabletop Simulator Lua API
  • 后端:Python Flask + Hypercorn
  • 通信:HTTP RESTful API
  • 编译:自定义Lexer/Parser + AST转换

🎯 当前进度

✅ 已完成(第一阶段)

  • GwentScript编译器全链路
  • Python后端骨架与事件系统
  • TTS Lua端核心功能
  • 初始发牌与换牌流程
  • Choose交互机制
  • Order能力完整流程
  • RoundEnd回合结算
  • 基础Bug修复

🔄 进行中(第二阶段)

  • 松鼠派卡组批量编译
  • 编译器语法修复
  • 卡牌效果逐一测试
  • 常用卡牌效果补齐

📅 计划中(第三阶段)

  • 完整双人对局流程优化
  • 第二个阵营支持
  • 效果触发完整性验证
  • 用户体验优化

🤝 贡献指南

欢迎贡献代码、报告Bug或提出建议!

开发原则

  1. 每个里程碑结束,都必须是一个可玩版本
  2. 批量编译的工作流必须稳定可靠
  3. 卡牌效果的准确性优先于数量

📄 许可证

本项目仅供学习和研究使用。

🙏 致谢

  • CD Projekt Red - 昆特牌游戏原作
  • Berserk Games - Tabletop Simulator平台
  • 所有贡献者和测试者

最后更新:2026年5月17日
当前版本:v1.4(第一阶段完成)
下一阶段:松鼠派卡组批量编译与测试