Skip to content

项目介绍 ​

Card Game Engine 是一个可扩展、插件化、事件驱动的卡牌游戏引擎核心,使用 Node.js + TypeScript 实现。

设计哲学 ​

Engine 不知游戏规则 ​

引擎核心本身不包含任何具体游戏规则。所有规则、动作、事件处理都通过 Plugin 注入。Engine 只提供通用能力:

  • 状态管理(GameState + stateUtils)
  • 卡牌、牌堆、玩家、区域的不可变数据结构
  • Action 派发与 Rule 校验
  • 事件总线
  • 插件生命周期(setup)
  • 快照、回放、状态校验、随机源

引擎核心文件不应出现任何游戏专属字符串(uno / skip-card / wild_draw4 / doudizhu 等)。

不可变 State ​

GameState 是不可变的。任何修改都会产生新的 GameState 并把 version 递增 1:

  • Action 处理路径上,引擎统一对每个 Action 仅 bump 一次版本
  • GameContext 的 mutation primitive(moveCard / setVariable / addPlayer ...)每次调用各 +1

通过 stateVersion 关联到 ActionHistory 与发出的 GameEvent,从而支持回放。

Action ≠ Event ​

  • Action — "我要做什么",由玩家或插件发起的意图
  • Event — "已经发生了什么",由 ActionHandler 在执行成功后产出

Action 触发 Event,Event 处理器可再触发新的 Action(链式 dispatch)。引擎通过 ActionQueue 把"递归 dispatch"转化为"迭代处理",避免调用栈无限增长。

Plugin 隔离 ​

Plugin 通过 GameContext 与 Engine 交互,不直接拿到 engine 引用。Plugin 在 setup、事件处理器中,以及(经由 RuleContext)规则中都会收到一个 GameContext。

确定性可回放 ​

所有随机决策必须经 ctx.random:

  • 严禁使用 Math.random()
  • 使用 SeededRandomProvider + 相同动作序列即可复现整局游戏
  • ReplayEngine 基于 (initialState, actionHistory) 确定性回放

状态校验可扩展 ​

StateValidator 内置 8 项通用不变量检查;通过 addStateCheck(name, check) 是通用能力,任意游戏可注入自己的不变量(如"牌堆总数恒为 54")。

模块划分 ​

模块路径说明
coresrc/core/GameEngine / GameState / GameContext / GameConfig / stateUtils
cardsrc/card/Card / CardZone / Deck
playersrc/player/Player
actionsrc/action/Action / ActionExecutor
eventsrc/event/GameEvent / EventBus
rulesrc/rule/Rule / RuleEngine
pluginsrc/plugin/GamePlugin / PluginManager
combinationsrc/combination/通用牌型系统(Detector / Comparator / CardQuery)
historysrc/history/ActionHistory / GameSnapshot
replaysrc/replay/ReplayEngine
validationsrc/validation/StateValidator / compareStates
randomsrc/random/RandomProvider(Math / Seeded)
pluginssrc/plugins/内置插件(StandardDeck / Turn / Draw / SimpleGame / Poker / Uno / Doudizhu)
serversrc/server/Phase 6 Game Server Runtime(HTTP + WebSocket)
utilssrc/utils/id 生成器

错误类型一览 ​

引擎与子系统定义了如下错误类,便于上层按错误类型分支处理:

错误类来源触发场景
ActionQueueOverflowErrorGameEngine单 tick 内 Action 数超过 maxActionsPerTick
EngineDestroyedErrorGameEngine引擎销毁后再调用公共 API
StateValidationErrorGameEngineStateValidator.validate 检测到违规
UnknownActionErrorActionExecutor未注册对应 type 的 handler
DuplicateActionHandlerErrorActionExecutor同一 type 被重复注册
DuplicateRuleErrorRuleEngineRule id 已注册
DuplicatePluginErrorPluginManager插件 id 已注册
PluginNotFoundErrorPluginManager按 id 取插件未找到

安装与运行 ​

要求 Node.js >= 18。

bash
# 安装依赖
npm install

# 构建(产物输出到 dist/)
npm run build

# 运行测试
npm test

# 类型检查
npm run typecheck

运行示例:

bash
npm run example            # 2 人 SimpleGame
npm run example:uno        # 3 人 UNO
npm run example:doudizhu   # 3 人斗地主
npm run example:replay     # 演示 ReplayEngine 确定性回放
npm run example:snapshot   # 演示 createSnapshot / restoreSnapshot

下一步 ​