☰
Guerrilla Checkers 环境实战指南:PufferLib 中不对称棋类自对弈的训练、检查点兼容与基准评估
2026/10/9 12:10:53 网站建设 项目流程
  • 强化学习
  • 深度学习
  • 人工智能

【免费下载链接】PufferLib

Puffing up reinforcement learning

项目地址:https://gitcode.com/gh_mirrors/pu/PufferLib
点击查看免费下载

Guerrilla Checkers 是 PufferLib 内置的一款棋盘类强化学习环境,它把 Checkers(国际跳棋)与 Go(围棋)的规则不对称地混合在一起,一方扮演"游击队"、另一方扮演"金币",形成了与常规对称棋类截然不同的博弈结构。本指南以仓库中的 ocean/guerrillacheckers/README.md 为核心,结合 ocean/guerrillacheckers/guerrillacheckers.h、ocean/guerrillacheckers/mcts.h 与 config/guerrillacheckers.ini 的源码与配置实现,完整讲解:如何理解这个不对称环境的状态与动作空间、如何启动标准 5c 自对弈训练、如何保持新旧检查点格式兼容、以及如何构建独立客户端并对候选模型做与 Puffer 40 基线的交叉对局评估。

读完本文,你将掌握一套可直接复用的训练、评估与基线对照工作流,并理解其中每一项关键配置在源码层面的真实作用。

游戏规则:Checkers 与 Go 的不对称混合

Guerrilla Checkers 在源码头部被明确注释为 "an asymmetric hybrid of Checkers and Go"(参见 ocean/guerrillacheckers/guerrillacheckers.h)。棋盘由8×8的 COIN 格网与7×7的游击队格点叠加而成:

常量值含义
GC_BOARD_W / GC_BOARD_H8 / 8COIN 棋子所在格网
GC_G_W / GC_G_H7 / 7游击队落子点网格
GC_COIN_CELLS64COIN 格点数
GC_G_CELLS49游击队格点数
GC_MAX_GUERRILLAS66游击队最多可投放的石子数
GC_ACTIONS256动作头宽度
GC_PASS_ACTION255非活跃槽位的确定性 pass 动作
GC_OBS_SIZE120观测长度(49 + 64 + 7)
GC_INVALID_ACTION_REWARD-1.0非法动作的负反馈
GC_MAX_BANKS8历史银行(对手池)最大数量

规则要点(均可从 ocean/guerrillacheckers/guerrillacheckers.h 的gc_*系列函数中确认):

  • 初始局面:puf_reset在 6 个固定坐标{3,2},{2,3},{4,3},{3,4},{5,4},{4,5}放置金币(见 guerrillacheckers.h)。
  • 游击队(Guerrilla)先手:每个回合可以在格点上连放两枚相邻的石子(第一枚与已有石子邻接,第二枚必须与第一枚邻接),GC_MAX_GUERRILLAS = 66是全局投放上限。
  • 金币(COIN)移动:金币沿对角方向移动,若跳越相邻的游击队格点则"吃掉"该石子;吃到后若仍可继续连跳,则强制继续(coin_must_capture标志)。
  • 包围吃子:一枚金币若被其四角全部占据游击石子,即被提走(gc_check_guerrilla_capture)。
  • 胜负判定(gc_check_victory):金币被全部清除 → Guerrilla 胜;游击队用尽 66 枚或场上无合法落点 → COIN 胜。
  • 超时判定(gc_check_timeout):到达max_episode_length步仍胜负未分时,直接判 Guerrilla 负(COIN 胜),因为 Guerrilla 的唯一胜利条件就是清空棋盘。

这种"一方通过围困蚕食、另一方通过跳吃反制"的非对称设计,是研究非对称博弈、不同行动节奏(回合内连放两子 vs 单步移动)与稀疏奖励的理想测试床。

检查点格式:Puffer 40 基线与新 5c 模型的兼容契约

仓库为 Guerrilla Checkers 保留了"原版 Puffer 40"作为新标准 5c 自对弈模型的评估基线。README 记录的唯一基线检查点如下:

CheckpointPurposeSHA-256
guerrillacheckers_weights.binOriginal Puffer 40f58615069b9a0e50105dd54b4729d366d602fe14b957a0042e4dc88089120398

两种布局的差异需要特别留意:

  • Puffer 40使用旧的587,264 字节 biased 布局;
  • 新训练的标准 5c 检查点使用586,240 字节 bias-free 布局,且带 value-head 行;
  • 独立评估器(standalone evaluator)会直接自动检测这两种格式,因此新旧检查点可以用同一套评估流程、在完全相同的输入上对局。

这得益于 guerrillacheckers.h 中的"原生 5c 构建契约":

#define OBS_SIZE GC_OBS_SIZE // 120 #define NUM_ATNS 1 #define ACT_SIZES {GC_ACTIONS} // 单头 256 动作 #define PUF_STEPS_PER_SEC 3

代码注释明确写道:保持与原始 Puffer 策略契约一致,是为了"让新旧检查点能够在相同输入上被评估"。这也解释了为什么 README 强调标准 5c 检查点带 value-head 行——旧模型只有 policy 头,新模型额外携带 value 头,评估器需要能分辨两者。

训练:真正交替的自对弈(genuine alternating self-play)

启动命令

./puffer train guerrillacheckers

该命令的 env 名guerrillacheckers由 config/guerrillacheckers.ini 的[base] env_name决定,训练器编译环境的方式见 build.sh(默认编译ocean/guerrillacheckers/guerrillacheckers.h,产出./puffer)。

自对弈机制:双逻辑策略槽位

README 明确描述了这套"真正交替自对弈 + 随机化 sides"的机制,其源码实现在Env结构体与gc_actor_slot/gc_rebuild_action_mask中:

  • slot 0 是可训练策略,slot 1 是当前或历史对手;
  • 每局开始时随机决定哪一方由哪个槽位扮演(side_cfg = 0表示每局随机),保证两边都被两个槽位充分训练到;
  • 非活跃槽位每步收到一个确定性 pass 动作(动作 255)。在 guerrillacheckers.h 中注释了设计意图:pass 动作在正常对局中不可能出现(它是右下角金币格网向外的越界移动),因此既能让等待槽位保持"每步一个动作"以维持 PPO 与循环状态的更新有效性,又不会被误用;
  • 两个槽位的循环状态(recurrent states)在每个游戏步都观察到完整局面,遵循已有的 Ocean Chess 自对弈约定(见 ocean/chess/chess.h);
  • 20% 的环境使用历史银行(historical bank),即对手来自冻结的历史快照池;
  • 对手交换只在所有 tagged 游戏都到达 episode boundary 之后进行,避免在局中打断,保证策略切换的干净边界。

关键配置逐项解读

config/guerrillacheckers.ini 是标准训练的规范配置,以下为各节参数及其源码层面的作用:

[base] env_name = guerrillacheckers # 一个 epoch = 4096 agents * 64 horizon = 262,144 agent steps。 # 每 20 个 epoch 存一次快照,历史池大约每 5.24M 步收到一个新策略。 checkpoint_interval = 20 [selfplay] enabled = 1 max_size = 100 seed = 42 # 冻结银行大约按快照产出频率刷新;加载推迟到所有 tagged 游戏到达 episode boundary。 opp_timeout_steps = 5_000_000 [vec] total_agents = 4096 num_buffers = 8 num_threads = 8 num_policies = 2 # 80% 当前对当前,20% 对历史池。 hist_policy_percent = 0.2 hist_policy_hidden_size = 128 hist_policy_num_layers = 2 [env] # 硬性步数上限;超时判 Guerrilla 失败(COIN 胜)。 max_episode_length = 256 # selfplay = 1:两个策略槽位交替 sides;历史池环境中 slot 0 是主策略,slot 1 是冻结对手。 # selfplay = 0:策略以 `side` 与内置 `opponent` bot 对局。 selfplay = 1 # slot 0(主策略)在自对弈中扮演的 side,或 bot 模式下 agent 的 side: # 0 = 每局随机,1 = Guerrilla,2 = COIN。 side = 0 # selfplay = 0 时的对手 bot:0 = random,1 = greedy(最大化吃子),2 = mcts。 opponent = 1 # MCTS 对手参数(opponent = 2 时使用)。迭代越多越强、越慢。 mcts_iterations = 256 mcts_exploration = 0.7 # rollout 策略:0 = random(忠实 UCT),1 = greedy(更强,尤其是 Guerrilla 侧)。 mcts_rollout = 1 [policy] hidden_size = 128 num_layers = 2 [train] total_timesteps = 100_000_000 gamma = 0.98 # 本环境是稀疏的 256 路动作头;action mask 负责合法性, # 低熵系数让探索不至于与 mask 过度对抗。 ent_coef = 0.0001

要点说明:

  • num_policies = 2对应自对弈中的两个逻辑槽位;hist_policy_percent = 0.2使 20% 环境接入历史银行,这与 README 中"Twenty percent of environments use the historical bank"一致;
  • side = 0的随机化语义在 guerrillacheckers.h 中实现:side_cfg为 1/2 时固定槽位归属,否则按随机位分配;
  • max_episode_length = 256直接驱动gc_check_timeout的超时判负逻辑;
  • ent_coef = 0.0001的低熵压力,是为了让探索不干扰 action mask 的合法性约束(非法动作会被 mask 屏蔽,且puf_step对非法动作按GC_INVALID_ACTION_REWARD = -1.0的"负向 no-op"处理,不即时判负,由超时兜底——详见 guerrillacheckers.h)。

观测、动作与奖励的编码细节

观测(OBS_SIZE = 120)

每个槽位看到完全相同的绝对棋盘编码(源码注释强调这是为了保持原始检查点契约),顺序为 guerrillacheckers.h:

  1. GC_G_CELLS = 49:游击队占位(0/1);
  2. GC_COIN_CELLS = 64:金币占位(0/1);
  3. 7 个标量:当前行动方 side id(Guerrilla=1 / COIN=2)、coin_must_capture标志、金币上一格(+1,-1 记 0)、游击队上一格(+1)、本回合已放子数、游击队总投放数、场上现存游击队石子数。

动作编码(256 路单头)

  • Guerrilla 动作:action = first * 4 + dir,其中first是 49 个格点之一,dir映射为四个方向({2,3,0,1},即下/右优先,保证 reset 后动作 0 合法),落子点在first与其该方向邻居——一个动作即"连放两枚相邻石子";
  • COIN 动作:action = src * 4 + dir,src为 64 个金币格之一,dir为四个对角方向;
  • 合法动作由gc_rebuild_action_mask实时枚举生成(gc_enumerate_legal),写入行动槽位的action_mask。

奖励设计

  • 每局终止时胜方 +1.0、负方 -1.0(自对弈中按slot_for_side[winner]结算到具体槽位);
  • 吃子即时奖励:Guerrilla 每次吃子 +0.05 × 枚数,COIN 每次 +0.03 × 枚数(guerrillacheckers.h);
  • 非法动作:GC_INVALID_ACTION_REWARD = -1.0作为负向 no-op;
  • invalid_rate统计每局决策中非法动作占比,是评估/训练日志中重要的健康度指标。

Log结构(guerrillacheckers.h)记录了 perf、score、episode_return/length、invalid_rate、按阵营统计的胜负场次、slot 0/1 得分,以及hist_score_bank[0..7]的历史银行分槽统计——这些字段在puf_log中全部导出为训练日志,用于监控自对弈进程。

评估:构建独立客户端并与 Puffer 40 基线对比

构建与对比命令

README 给出的完整评估流程:

./build.sh guerrillacheckers --fast ./guerrillacheckers --compare-candidate 1000 \ .runtime/checkpoints/guerrillacheckers/<run>/<checkpoint>.bin
  • 第一步构建独立客户端(standalone client)并产出可执行文件./guerrillacheckers;
  • 第二步让原生候选模型与原始 Puffer 40从两侧各下 1000 局(--compare-candidate 1000为局数参数),候选检查点路径位于.runtime/checkpoints/guerrillacheckers/<run>/<checkpoint>.bin;
  • 独立客户端同时内建了人类对战能力:在 raylib 窗口中按住 Left Shift 点击即可"先选点、再选目标"地手动走棋(gc_human_controls,见 guerrillacheckers.h)。

关于构建的一般性说明:仓库根目录的 build.sh 同时支持./build.sh guerrillacheckers(原生训练/评估,产出./puffer)、./build.sh guerrillacheckers mybin(自定义输出名)、以及--cpu模式构建独立 CPU 评估二进制(产出./build/cpu_guerrillacheckers,要求环境头必须typedef obs_t)。README 中记录的--fast是针对独立客户端的快速构建选项,以其为准即可。

基线交叉对局表(每格 100 局,Guerrilla wins - COIN wins)

README 记录的基线字段为每格 100 局、以"Guerrilla 胜 - COIN 胜"形式展示:

Guerrilla / COINRandomGreedyPuffer 40MCTS 2KMCTS 10K
Random8-920-1000-1000-1000-100
Greedy98-233-671-990-1000-100
Puffer 4096-499-115-8512-889-91
MCTS 2K99-1100-050-5030-7011-89
MCTS 10K100-0100-084-1681-1965-35

分侧 Bradley-Terry Elo(锚定 Elo 1500)

README 同时给出了**分侧(side-specific)**的 Bradley-Terry 拟合 Elo,锚定基准为 1500,覆盖全部 10 个分侧条目:

BotGuerrilla EloCOIN Elo
Random338727
Greedy11201189
Puffer 4016361879
MCTS 2K18341969
MCTS 10K22002108

两点值得注意:同一策略扮演不同阵营时强度差异明显——Puffer 40 的 COIN Elo(1879)显著高于其 Guerrilla Elo(1636),MCTS 10K 则反过来(Guerrilla 2200 vs COIN 2108),这与环境的不对称规则直接相关;基线表中 MCTS 10K 作为 Guerrilla 对阵任何对手都保持压倒性胜率,而作为 COIN 对阵同级别 MCTS 对手时胜率下降(65-35 vs 同 Bot 行),这些数据是评估新模型时必须对照的分侧基线。

内置对手与 MCTS 实现

当selfplay = 0(bot 模式)时,agent 在puf_step内与内置 bot 对局。对手由opponent参数选择(枚举见 guerrillacheckers.h):

  • Random(GC_BOT_RANDOM = 0):均匀随机挑选合法动作;
  • Greedy(GC_BOT_GREEDY = 1):使用gc_action_capture_score对每个合法动作做不改动棋盘的即时吃子评估,选取吃子数最多的动作(并列时随机),见gc_greedy_pick;
  • MCTS(GC_BOT_MCTS = 2):完整 UCT 搜索,实现在 ocean/guerrillacheckers/mcts.h 中。

MCTS 对手的实现要点(从源码结构看):

  • 移植自参考实现nico/guerrillacheckers/src/mcts.nim,采用完美信息单树 UCT:每步决策构建一棵树,wins 从"移入该节点的玩家"视角存储,因此最大化子节点胜率即选择当前行动方的最优着法;
  • 节点池化:每次迭代最多展开一个节点,因此池大小取itermax + 1(mcts.h),迭代循环只克隆棋盘状态(GuerrillaCheckers s = *env后清空 agent 缓冲);
  • UCB1 选择:探索常数默认0.7(≈ sqrt(2)/2,与参考引擎一致),由mcts_exploration覆盖;
  • rollout 策略二选一(mcts_rollout):0为均匀随机 playout(忠实 UCT),1为 greedy 吃子最大化 playout——源码注释指出 greedy rollout 在宽阔的 Guerrilla 侧明显更强,但单次迭代成本更高;
  • 选择最终着法时采用最高访问次数子节点(most-visited child)而非最高胜率,这是 UCT 的标准稳健做法。

MCTS 的mcts_iterations(默认 256)、mcts_exploration(默认 0.7)、mcts_rollout(默认 1)三项旋钮全部来自 config/guerrillacheckers.ini 的[env]节,在puf_init中读取并存入Env结构体。

实操建议与注意事项

  1. 用基线先行验证评估链路:在评估任何新候选模型前,先用guerrillacheckers_weights.bin(SHA-256f58615069b9a0e50105dd54b4729d366d602fe14b957a0042e4dc88089120398)跑一遍--compare-candidate,确认评估器能同时识别 587,264 字节的 biased 布局与 586,240 字节的 bias-free + value-head 布局。
  2. 关注分侧表现而非总胜率:由于规则不对称,同一模型的 Guerrilla Elo 与 COIN Elo 往往相差数百点。评估新模型时应分别对照 README 的十个分侧条目,而不是只看整体胜率。
  3. 自对弈健康度监控:训练日志中的invalid_rate、slot_0_score_as_guerrilla/slot_0_score_as_coin与hist_score_bank_*分别反映合法性、分侧强度与历史对手池的对抗进程;对手池交换被刻意推迟到所有 tagged 游戏到达 episode boundary,这是保证策略切换干净的关键设计。
  4. 超时兜底语义:max_episode_length超时判 Guerrilla 负而非当前行动方负(guerrillacheckers.h 注释),这在 bot 模式下避免超时总是落在学习者头上——理解这一点对解释边界样本的奖励归属很重要。
  5. 构建环境:所有构建入口统一在仓库根目录的 build.sh,无需修改任何源码即可完成./puffer train guerrillacheckers、独立客户端构建与--compare-candidate评估全流程。

小结

Guerrilla Checkers 是一个罕见的非对称混合规则棋盘博弈,PufferLib 为其提供了完整的训练、评估与基线闭环:genuine alternating self-play的双槽位机制与历史银行保证了稳定的对手进化;586,240 / 587,264两种检查点布局的自动识别让新旧模型可以在同一契约下对局;分侧 Elo 与交叉胜负表则给出了透明、可复现的评估锚点。对研究非对称博弈、回合节奏差异与稀疏奖励的读者来说,这是一套可以立即上手的实验台。

  • 强化学习
  • 深度学习
  • 人工智能

【免费下载链接】PufferLib

Puffing up reinforcement learning

项目地址:https://gitcode.com/gh_mirrors/pu/PufferLib
点击查看免费下载

相关推荐

上一篇:Flink Hive Dialect ALTER 语句完全指南:数据库、表与视图的元数据变更实战
下一篇:Apache APISIX Script(脚本)机制详解:在 Route 上直接运行自定义 Lua 代码

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询