Stephen Diehl 用 Lean 4 形式化验证了整个 Caverna 桌游,证明 furnishing rush 是唯一的最优策略。这是一个极端但精彩的形式化方法应用案例。
📖 Read Original Article🎮 项目概览
3,000
Lean 4 代码行数
19
模块数量
176
机器检查证明
2,880
游戏配置数量
🏗️ 技术方法:标签转换系统 (LTS)
标签转换系统是一个三元组 (S, A, T):
- S - 状态集合
- A - 动作集合
- T ⊆ S × A × S - 转换关系
在 Lean 4 中,LTS 定义为:
structure LTS (State : Type) (Action : Type) where
init : State -> Prop
trans : State -> Action -> State -> Prop
可达性证明
Reachability 是一个归纳类型:
inductive Reachable (sys : LTS State Action) : State -> Prop where
| init : forall s, sys.init s -> Reachable sys s
| step : forall s a s', Reachable sys s -> sys.trans s a s' -> Reachable sys s'
这比测试更强。测试检查特定的玩牌序列。不变式证明覆盖每一种可能的合法移动序列,包括人类永远不会玩的序列。
📐 游戏建模
完整的游戏状态
structure GState where
round : Nat
phase : Phase
p1 : FullPlayer
p2 : FullPlayer
p1IsFirst : Bool
placementsLeft : Nat
acc : AccState
occupiedSpaces : List ActionSpaceId := []
harvestSchedule : Nat -> HarvestEvent
wishIsUrgent : Bool := false
转换关系
转换关系是一个单一函数,对 (phase, act) 进行匹配。每个 case 都是一条游戏规则。最后一行很美:
| _, _ => False
这意味着:任何未明确列出的动作都是非法的。转换关系是封闭的。没有未定义行为,没有边缘情况,没有"规则没说我不能"。如果不在 match 中,就不会发生。
🎯 核心结论:Furnishing Rush 是最优策略
主要结果:证明 furnishing rush 是每种配置下的弱最优策略。它是对每个对手的最优回应,无论牌序如何或收获标记落在哪里。
游戏时间线
- 12 轮游戏
- 第 4 轮 "Wish for Children" 允许第一次家庭成长(2 → 3 矮人)
- 第 8 轮 "Family Life" 允许第二次家庭成长(3 → 5)
关键洞察
没有成长:44 次矮人放置
一次成长(第4轮):47 次
两次成长:56 次
从"不成长"到"两次成长"的 27% 差距是游戏中最主要的策略杠杆。
🔬 依赖类型的妙用:让非法状态不可构造
用依赖类型让非法游戏状态无法构造。武器是最清晰的例子:
structure Weapon where
strength : Nat
h__min : strength >= 1
h__max : strength <= 14
每个 Weapon 值都带有其强度在范围内的证明。这意味着 forgeWeapon 必须产生证据证明它返回的值是有效的。
🔗 资源链接
💡 启示
"My friends think this is excessive. My friends also lose at Caverna."
这是一个极端但精彩的形式化方法应用案例,展示了:
- 有限确定性完美信息游戏可以用形式化方法分析
- Lean 4 的依赖类型系统非常适合建模游戏规则
- 不变式证明可以覆盖测试无法覆盖的边缘情况
- 形式化方法不只是用于关键系统,也可以用于有趣的问题