一个基于 Tabletop Simulator (TTS) 平台的昆特牌(Gwent)游戏实现,采用 Python 后端 + Lua 前端的双层架构,支持自定义卡牌脚本编译和事件驱动的游戏逻辑。
本项目实现了完整的昆特牌双人对局系统,包括:
- GwentScript 编译器:将自定义的 GC 语法编译为 Python 代码
- Python 后端服务器:处理游戏逻辑、事件分发和卡牌效果
- TTS Lua 客户端:负责游戏界面、交互和视觉效果
- 完整的事件系统:支持 Deploy、Order、RoundEnd 等多种事件类型
- ✅ 初始发牌:双方各发10张手牌
- ✅ 换牌阶段:支持重新调度手牌(Redeal)
- ✅ 回合制对战:交替出牌,支持Pass机制
- ✅ 回合结算:自动计算战力、判定胜负
- ✅ 三局两胜:完整的Bo3对局流程
- ✅ 墓场管理:回合结束时卡牌自动移入墓场
- ✅ 近战排(Melee):双方各有近战区域
- ✅ 远程排(Range):双方各有远程区域
- ✅ 墓场(Grave):已使用卡牌的归宿
- ✅ 牌库(Deck):未抽到的卡牌
- ✅ 手牌区(Hand):玩家手中的卡牌
- ✅ 单位卡(Unit):具有战力的基础卡牌
- ✅ 谋略卡(Stratagem):开局自动部署的特殊卡
- ✅ 能力卡(Ability):提供被动效果的卡牌
- ✅ 领袖卡(Leader):玩家领袖(待完善)
- ✅ 战力(Power):基础战力和当前战力
- ✅ 护甲(Armor):吸收伤害的护盾
- ✅ 人口(Provision):卡组构建限制
- ✅ 阵营(Faction):卡牌所属阵营
- ✅ 稀有度(Rarity):金/银/铜/特殊
- ✅ 颜色(Color):紫色/黄色(玩家标识)
- ✅ 护甲标记:显示剩余护甲值
- ✅ 充能标记:显示可用次数
- ✅ 状态标记:坚韧、免疫、锁定等(框架已搭建)
- ✅ Deploy:卡牌部署到战场时触发
- ✅ Order:玩家点击Order按钮时触发(异步支持)
- ✅ RoundEnd:回合结束时触发
- ✅ TurnStart:回合开始时触发(框架已搭建)
- ✅ DamageReceived:受到伤害时触发(框架已搭建)
- ✅ 自身过滤:
[self]- 仅响应自身触发的事件 - ✅ 友方过滤:
[ally]- 仅响应友方触发的事件 - ✅ 敌方过滤:
[enemy]- 仅响应敌方触发的事件 - ✅ 名称过滤:
[name('卡牌名')]- 特定名称的卡牌 - ✅ 标签过滤:
[tag('标签')]- 具有特定标签的卡牌
# 增益/减益
card.boost(amount) # 增加战力
card.damage(amount) # 造成伤害
card.heal(amount) # 治疗(移除伤害)
# 位置判断
card.onBattleGround() # 是否在战场上
card.inGrave() # 是否在墓场
card.inDeck() # 是否在牌库
# 位置移动
card.jumpTo(target) # 移动到指定区域
# target: "allyRows", "enemyRows", "battleGround", 或具体坐标# 异步选择目标
target = await card.choose(conditions, type)
# conditions: allyRows, enemyRows, battleGround
# type: "unit", "stratagem" 等卡牌类型# 事件过滤
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) # 获取卡牌标签- ✅ 按钮创建:Deploy后自动添加Order按钮
- ✅ 按钮点击:玩家点击触发Order事件
- ✅ 异步执行:支持async/await异步操作
- ✅ 目标选择:Order中可使用choose选择目标
- ✅ 按钮移除:使用后可调用remove_button()移除
async def Order1(event):
if not filter_event(event, [], self_reference):
return
target = await choose(allyRows, "unit")
target.boost(1)- ✅ 双方都Pass后触发
- ✅ 在卡牌移入墓场之前触发
- ✅ 卡牌仍在战场上,可正确判断位置
def RoundEnd1(event):
if not filter_event(event, [self_reference], self_reference):
return
if self_reference.onBattleGround():
self_reference.boost(1) # 回合结束增益GC源代码 (.txt)
↓ [Lexer + Parser]
AST抽象语法树 (JSON)
↓ [ASTToPython.py]
Python代码 (.py)
↓ [Import]
运行时加载
- ✅ 事件订阅:
Deploy[self],Order[self],RoundEnd[self] - ✅ 条件判断:
?,?!,!(if/else) - ✅ 循环语句:
for list as var - ✅ 赋值运算:
=,+=,-=,*=,/= - ✅ 选择机制:
choose num from place where filter as var - ✅ 函数调用:
boost(),damage(),jumpTo()等
Deploy[self]
boost(2)
RoundEnd[self]
onBattleGround()?
boost(1)
- ✅ HTTP POST:事件发送到后端
- ✅ JSON格式:结构化数据传输
- ✅ Action系统:后端指令前端执行操作
- ✅ power:修改卡牌战力
- ✅ heal:治疗卡牌
- ✅ jumpTo:移动卡牌位置
- ✅ choose:显示选择界面
- ✅ addButton:添加交互按钮
- ✅ removeButton:移除交互按钮
- ✅ spawnCard:生成新卡牌
- ✅ database.json:存储所有卡牌元数据
- ✅ 名称映射:多语言支持(中文)
- ✅ 标签系统:卡牌分类和过滤
- ✅ 属性定义:战力、护甲、人口等
- ✅ 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 asynciopython HostTest.py- 在TTS中创建游戏桌
- 打开脚本编辑器(Scripting → Editor)
- 粘贴
code.lua的内容 - 保存并运行
python ASTToPython.py GCodesOriginal/card201727.txt- ROADMAP.md - 项目开发路线图
- ROUND_END_TEST.md - RoundEnd事件详细说明
- ORDER_TEST.md - Order能力完整流程
- 里程碑1.3完成总结.md - Order能力实现总结
- 里程碑1.4完成总结.md - 回合结算实现总结
- 前端:Tabletop Simulator Lua API
- 后端:Python Flask + Hypercorn
- 通信:HTTP RESTful API
- 编译:自定义Lexer/Parser + AST转换
- GwentScript编译器全链路
- Python后端骨架与事件系统
- TTS Lua端核心功能
- 初始发牌与换牌流程
- Choose交互机制
- Order能力完整流程
- RoundEnd回合结算
- 基础Bug修复
- 松鼠派卡组批量编译
- 编译器语法修复
- 卡牌效果逐一测试
- 常用卡牌效果补齐
- 完整双人对局流程优化
- 第二个阵营支持
- 效果触发完整性验证
- 用户体验优化
欢迎贡献代码、报告Bug或提出建议!
- 每个里程碑结束,都必须是一个可玩版本
- 批量编译的工作流必须稳定可靠
- 卡牌效果的准确性优先于数量
本项目仅供学习和研究使用。
- CD Projekt Red - 昆特牌游戏原作
- Berserk Games - Tabletop Simulator平台
- 所有贡献者和测试者
最后更新:2026年5月17日
当前版本:v1.4(第一阶段完成)
下一阶段:松鼠派卡组批量编译与测试