~cytrogen/blog-public

ref: 88eebf3dfdd8ab819fa1a84e1976a8a75d5af2b6 blog-public/posts/cc52.html -rw-r--r-- 48.7 KiB
88eebf3dCytrogen Deploy 2026-02-19 08:34:27 4 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
<!DOCTYPE html><html lang="zh" data-theme="dark"><head><meta charset="utf-8"><meta name="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>玩《茂林源记》 · Cytrogen 的个人博客</title><meta name="description" content="《茂林源记》,或称 Root(以下也这么称呼),是一个区域控制类桌游。虽然这么说,但它的标签还是很多的,例如德式桌游标准的得分制、应该被划分给美式桌游的阵营机制等等。我先前为这款游戏写过一些评价,本来没有打算继续去写该游戏的说明,但介于自己刚写了个扫雷的入门说明,最终还是写下了这篇文章。"><link rel="icon" href="../favicon.png"><link rel="canonical" href="https://cytrogen.icu/posts/cc52.html"><link rel="webmention" href="https://webmention.io/cytrogen.icu/webmention"><link rel="me" href="https://m.otter.homes/@Cytrogen"><link rel="me" href="https://github.com/cytrogen"><meta name="fediverse:creator" content="@Cytrogen@m.otter.homes"><link rel="preload" href="../fonts/opensans-regular-latin.woff2" as="font" type="font/woff2" crossorigin="anonymous"><style>@font-face {
  font-family: 'Open Sans';
  src: url('../fonts/opensans-regular-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  size-adjust: 107%;
  ascent-override: 97%;
  descent-override: 25%;
  line-gap-override: 0%;
}
</style><script>(function() {
  try {
    // 优先级:用户选择 > 系统偏好 > 默认浅色
    const saved = localStorage.getItem('theme');
    const theme = saved || 
      (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
    
    document.documentElement.setAttribute('data-theme', theme);
    document.documentElement.style.colorScheme = theme;
  } catch (error) {
    // 失败时使用默认主题,不阻塞渲染
    document.documentElement.setAttribute('data-theme', 'light');
  }
})();
</script><link rel="stylesheet" href="../css/ares.css"><script data-netlify-skip-bundle="true">(function() {
  document.addEventListener('DOMContentLoaded', function() {
    const theme = document.documentElement.getAttribute('data-theme');
    const pageWrapper = document.getElementById('page-wrapper');
    if (pageWrapper && theme) {
      pageWrapper.setAttribute('data-theme', theme);
    }
  });
})();

</script><!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 8.1.1"><link rel="alternate" href="atom.xml" title="Cytrogen 的个人博客" type="application/atom+xml">
</head><body><div id="page-wrapper"><a class="skip-link" href="#main-content">跳到主要内容</a><div class="wrap"><header><a class="logo-link" href="../index.html"><img src="../favicon.png" alt="logo"></a><div class="h-card visually-hidden"><img class="u-photo" src="https://cytrogen.icu/favicon.png" alt="Cytrogen"><a class="p-name u-url u-uid" href="https://cytrogen.icu">Cytrogen</a><p class="p-note">Cytrogen 的个人博客,Cytrogen's Blog</p><a class="u-url" rel="me noopener" target="_blank" href="https://m.otter.homes/@Cytrogen">Mastodon</a><a class="u-url" rel="me noopener" target="_blank" href="https://github.com/cytrogen">GitHub</a></div><nav class="site-nav"><div class="nav-main"><div class="nav-primary"><ul class="nav-list hidden-mobile"><li class="nav-item"><a class="nav-link" href="../index.html">首页</a></li></ul><div class="nav-tools"><div class="language-menu"><button class="language-toggle" type="button"><svg class="icon icon-globe" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855A7.97 7.97 0 0 0 10.855 12H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z"></path></svg><span>中文</span></button><div class="language-dropdown"></div></div></div><div class="nav-controls"><div class="more-menu hidden-mobile"><button class="more-toggle" type="button"><span>更多</span><svg class="icon icon-chevron-down" width="12" height="12" viewBox="0 0 12 12" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 8.825c-.2 0-.4-.1-.5-.2l-3.3-3.3c-.3-.3-.3-.8 0-1.1s.8-.3 1.1 0l2.7 2.7 2.7-2.7c.3-.3.8-.3 1.1 0s.3.8 0 1.1l-3.3 3.3c-.1.1-.3.2-.5.2z"></path></svg></button><div class="more-dropdown"><ul class="dropdown-list"><li class="dropdown-item"><a class="nav-link" href="../archives/index.html">归档</a></li><li class="dropdown-item"><a class="nav-link" href="../categories/index.html">分类</a></li><li class="dropdown-item"><a class="nav-link" href="../tags/index.html">标签</a></li><li class="dropdown-item"><a class="nav-link" href="../about/index.html">关于</a></li><li class="dropdown-item"><a class="nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></div><div class="theme-switcher"><button class="theme-toggle" type="button" role="switch" aria-pressed="false" aria-label="切换主题"><div class="theme-icon moon-icon"><svg class="icon icon-moon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"></path></svg></div><div class="theme-icon sun-icon"><svg class="icon icon-sun" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"></path></svg></div></button></div><details class="mobile-menu-details hidden-desktop"><summary class="hamburger-menu" aria-label="nav.menu"><svg class="icon icon-bars" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"></path></svg><span class="menu-text">nav.menu</span></summary><div class="mobile-menu-dropdown"><ul class="mobile-nav-list"><li class="mobile-nav-item"><a class="mobile-nav-link" href="../index.html">首页</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../archives/index.html">归档</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../categories/index.html">分类</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../tags/index.html">标签</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../about/index.html">关于</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></details></div></div></div></nav></header><main class="container" id="main-content" tabindex="-1"><div class="post"><article class="post-block h-entry"><div class="post-meta p-author h-card visually-hidden"><img class="author-avatar u-photo" src="../favicon.png" alt="Cytrogen"><span class="p-name">Cytrogen</span><a class="u-url" href="https://cytrogen.icu">https://cytrogen.icu</a></div><a class="post-permalink u-url u-uid visually-hidden" href="https://cytrogen.icu/posts/cc52.html">永久链接</a><div class="p-summary visually-hidden"><p>《茂林源记》,或称 Root(以下也这么称呼),是一个区域控制类桌游。虽然这么说,但它的标签还是很多的,例如德式桌游标准的得分制、应该被划分给美式桌游的阵营机制等等。我先前为这款游戏写过一些评价,本来没有打算继续去写该游戏的说明,但介于自己刚写了个扫雷的入门说明,最终还是写下了这篇文章。</p></div><div class="visually-hidden"><a class="p-category" href="../categories/%E6%B8%B8%E6%88%8F%E8%AF%B4%E6%98%8E/">游戏说明</a><a class="p-category" href="../tags/%E6%A1%8C%E9%9D%A2%E6%B8%B8%E6%88%8F/">桌面游戏</a></div><a class="u-syndication visually-hidden" target="_blank" rel="noopener" href="https://m.otter.homes/@Cytrogen/116076989771657767">https://m.otter.homes/@Cytrogen/116076989771657767</a><h1 class="post-title p-name">玩《茂林源记》</h1><div class="post-info"><time class="post-date dt-published" datetime="2026-02-15T05:00:00.000Z">2/15/2026</time><time class="dt-updated visually-hidden" datetime="2026-02-19T07:42:07.353Z"></time></div><div class="post-content e-content"><html><head></head><body><p>《茂林源记》,或称 Root(以下也这么称呼),是一个区域控制类桌游。虽然这么说,但它的标签还是很多的,例如德式桌游标准的得分制、应该被划分给美式桌游的阵营机制等等。我先前为这款游戏写过一些评价,本来没有打算继续去写该游戏的说明,但介于自己刚写了个扫雷的入门说明,最终还是写下了这篇文章。</p>
<span id="more"></span>
<p>首先需要说明,桌游和其他电子游戏一样,是一个很大的类。休闲的桌游,如爆炸猫,跟大型的桌游,如很知名的 D &amp; D,区别是很大很大的。在决定游玩 Root 之前,请务必考虑一下自己到底是什么桌游玩家 ——<span class="emphasis"> 愿意花时间钻研吗?愿意仔细阅读说明书,且游玩期间遇到不懂的地方也会去认真查询吗?</span></p>
<p>问这些问题的原因是,Root 其实卡在一个颇为尴尬的地方:它既没有大型桌游那么难懂,但入门门槛也足以劝退休闲玩家。这也是为什么我很难线下跟他人玩 Root,愿意尝试的就不多,看到说明书和规则书的还想继续玩的是少数;最麻烦的是教完一个人规则和至少一个阵营后,天也暗了,大家没有那么多空闲时间,只能等几个月再约。</p>
<p>好啦虽然我抛出了这么多预警,对于依然想要继续学习的你们来说,Root 可能并没有那么可怕!实际上,就像我刚才说的,它无法跟更大的桌游比较。既然只需要一天就能教会一个新人,它的困难程度可想而知,并没有那么高,难的地方只是它的阵营机制。</p>
<p>说了这么多,让我们回归正题吧,一起进入这片广大的茂林吧!</p>
<h3 id="基础规则"><a class="markdownIt-Anchor" href="#基础规则"></a> 基础规则</h3>
<p>Root 里,每个阵营的回合都结束后,一轮才算结束。也就是说,玩家甲开始回合,到玩家乙的回合结束,这算一轮。每个阵营的回合会经历三个阶段,也是三个时间段:清晨、白天和晚上。在这三个阶段里,不同阵营能够做的事情都不相同。</p>
<p>通常而言,在设置期间,每个玩家会获得自己的阵营板、阵营所需要的所有米宝和令牌,以及 3 张牌。说到卡牌,该游戏有三个基础类型,或者说领地类型:老鼠、兔子和狐狸,他们是这个森林里的老百姓,更详细的背景设定我之后会补充。该游戏的大多数卡牌都需要锻造后才能发挥作用。在 Root 里,如果手牌超过 5 张,就必须在晚上阶段结束时丢弃直到手上只有 5 张牌。</p>
<p>地图上的地点和路线都是固定的,不过地点的类型可以随机,不过我个人推荐在学会游玩 Root 之前,只玩它的默认地图,因为类型分布最为平均。</p>
<p>必须要记住的是,Root 是一个区域控制游戏,<strong>「占领的领地」和地点是两个不同的概念</strong>。当你的士兵米宝和建筑物在一个地点上,数量超过其他阵营的士兵和建筑物,就算占领了该地点。当移动士兵时,出发地点和目标地点必须至少有一个在你进行移动之前、被你的阵营占领。这是 Root 在移动士兵上的基础规则。一次可以移动的士兵数量是随意的,想要移动多少就移动多少。</p>
<p>再就是「建筑物」,查看地图时你会发现,地点上都有数个空格,这些便是放置建筑物的格子。当一个地点上没有空闲的建筑物格子,玩家们就不可以在该地点上放置更多的建筑物了。建筑物并不属于令牌的一种,令牌是圆形的,建筑物是方形的。建筑物在计算占领权会被算上,令牌则不算。</p>
<p>战斗需要用到两个骰子,这两个骰子都只能投出 0/1/2/3 这四个点数。假设玩家甲和乙丢出了 1 和 3 这两个点数,且甲和乙在这个地点上的士兵数量分别是 2 和 3。在 Root 的战斗中,发起战斗的一方会取点数最大的那个骰子,被攻击的一方则拿点数最小的骰子 —— 乙作为攻击方,一共有 3 个士兵,点数也是 3,这意味着他的 3 个士兵都可以各杀死一个敌人。尽管甲的士兵数量是 2,但拿到的 1 点数让他只能让 1 个士兵杀死一个敌人。结果就是,乙的 3 个士兵杀死了甲的 2 个士兵,多出了 1 次攻击,而甲的 1 个士兵杀死了乙的 1 个士兵。</p>
<p>当地点上的士兵都死掉了,多出来的攻击会算给令牌和建筑物。它们都不具备攻击能力,所以也无法战斗。如果攻击方攻击的地点上只有对方的令牌或者建筑物,那么无论投出多少点的骰子,都会另加 1 点伤害。并且,只要有 1 个令牌或者建筑物被摧毁,攻击者都可以额外拿取 1 分。如果有多个令牌或者建筑物,那么由被攻击的一方决定哪一个应当被移除。</p>
<p>要在 Root 里获胜,通常是靠先得到 30 分。至于如何得分,每个阵营的方式也都不一样。所以可以看出来,该游戏的绝大多内容都在阵营上,而因为阵营除了游侠这个特殊阵营外都不能重复,所以在游玩自己的阵营时,也需要提防他人的阵营得分。这也是 Root 入门时的难点: <strong>记住所有阵营的机制和得分方法</strong></p>
<h3 id="阵营机制说明"><a class="markdownIt-Anchor" href="#阵营机制说明"></a> 阵营机制说明</h3>
<h4 id="猫女侯爵"><a class="markdownIt-Anchor" href="#猫女侯爵"></a> 猫女侯爵</h4>
<p>也有翻译称其为「猫咪贵族」。在原文中用的 marquis 其实是法语的「女侯爵」的意思,这里就保留这层意思吧,不过后面都会简称为「猫咪」就是了。</p>
<p>猫咪们在打跑了原本统治了森林的「飞鹰王朝」后,决心一路向工业化进发 —— 砍树盖房子!猫咪可以放置三个种类的建筑物,且加分方式是靠放置建筑物。</p>
<p>猫咪在开局阶段里优先级最高,可以选择地图上的任意一个角落作为自己城堡的落脚点,然后可以在城堡所在的地点或者相邻的地点内免费放置一个伐木场、一个工坊,和一个招兵所。</p>
<p>我用了「免费」这个词,为什么呢,因为是「砍树」盖房子,原先这些建筑物都需要使用「木材」才能建造。木材作为一个令牌,又该如何获取呢?答案是靠猫咪的伐木场。嗯,这下便好理解了:猫咪通过建造伐木场来获取木材,又消耗木材来建造建筑物,建造建筑物还能加分,且场上相同类型的建筑物盖得越多、 加分越多。这便是猫咪主要的玩法。</p>
<p>猫咪的士兵足足有 25 个,到后面我介绍越来越多的阵营时,你便会发现这个数量有多么夸张。开局阶段里,猫咪需要在地图的所有地点上放置一个士兵,除了城堡斜对面的那一个角落。</p>
<p>清晨阶段,猫咪只能做一件事,那便是在场上所有伐木场所在的地点放置一个木材令牌,相当于每个伐木场都砍到了木头。白天阶段里则分两个步骤:一是激活场上的工坊来锻造卡牌,二是按照任意顺序和组合执行最多三项操作。</p>
<p>先说猫咪的锻造。卡牌的锻造条件都要求一个阵营的可锻造单位有足够的数量,且位于正确的地点类型。比方说有一张牌要求有两个兔子类型,那对于猫咪而言,就需要在兔子类型的地点内先建造两个工坊,才能锻造该卡牌。这些可锻造单位,一回合只能使用一次。这对猫咪来说,不是一个好兆头,因为锻造卡牌之前,猫咪需要先消耗木头和行动次数来建造建筑物。</p>
<p>再来说猫咪的行动:战斗、行军、招募、建造建筑物、加班。</p>
<p>其中战斗没什么好说的,剩下三个都有着猫咪自己的特色。行军是加强的移动,一次行军相当于移动两次,且移动时仍然可以随意决定要移动的士兵数量;招募会在每个招兵所所在的地点放置一个新士兵,不过该操作 <strong>每个回合只能执行一次</strong></p>
<p>建造建筑物需要单独拉出来说。一个玩家们经常忘记的猫咪规则是,想要建造建筑物的地点首先得是被猫咪占领的,且该地点需要和木材所在的地点形成一条完全被猫咪占领的路线才行。也就是说,<span class="emphasis">木材必须从猫咪占领的地点,通过一系列也被猫咪占领的地点,才能抵达猫咪打算建造建筑物的已被占领地点</span>。接着玩家需要在阵营板上选择建造哪一个建筑物、查看该建筑物如果被建造了需要消耗多少木材(每个类型的建筑物所需要的木材以及得到的分数都是独立开来的),并消耗这些木材。</p>
<p>猫咪也可以通过消耗一张手牌里的飞鹰类型的卡牌来为自己添加一次额外的操作次数。咦,什么是飞鹰类型?这是有别于基础三类型的第四个类型,对许多阵营而言,它可以被当成是「任意一个类型」,相当特殊。</p>
<p>至于加班,它需要你选中一个伐木场,并根据该伐木场所在的地点类型,消耗一张同类型的卡牌来获取一个木材令牌。因为飞鹰卡牌可以被视作任意一个类型,所以也可以用在这里。</p>
<p>到晚上阶段,猫咪需要补充一张手牌。如果招兵所被建造得够多,你会根据阵营板上的卡牌图标而获取额外的手牌。</p>
<p>最后说一下猫咪的被动技能:其他阵营不能在城堡所在的地点内放置任何令牌或者建筑物或者士兵,他们只能将士兵移动到该地点。每当任意数量的猫咪士兵从一个地点中被移除,猫咪可以选择消耗一张匹配该地点类型的卡牌,将这些被移除的士兵放置在城堡所在的地点。如果城堡被移除,它会在该局游戏内完全被移除,拿不回来。</p>
<h4 id="飞鹰王朝"><a class="markdownIt-Anchor" href="#飞鹰王朝"></a> 飞鹰王朝</h4>
<p>Eyrie 虽然是鹰巢的意思,但是「鹰巢王朝」总感觉不好听,故使用官方翻译「飞鹰王朝」。</p>
<p>飞鹰是森林过去的霸主,被猫咪打跑后,希望通过重新占领领地,来恢复自己的尊严。不过他们也是一个强迫症种族,每日的行动必须完全遵守「法令」的顺序,否则民众会陷入混乱、推翻当下的领袖。</p>
<p>清晨阶段按照顺序分为三个步骤:一、如果没有手牌,则抽一张牌;二、必须将手牌的一张或两张牌添加到法令区中,但只能有一张是飞鹰牌;三、如果地图上没有鸟巢建筑物,则在一个有最少士兵的空地上放置一个鸟巢和三个士兵。</p>
<p>白天阶段按照顺序分为两个步骤:一、激活鸟巢锻造卡牌;二、必须严格从最左边的列开始,向右依次结算法令。</p>
<p>不过在说明法令如何运作之前,我们需要先看一眼飞鹰的开局阶段。在游戏开始时,飞鹰玩家需要从四张领袖卡牌中选择一张作为初始领袖放置在阵营板上。每位领袖不仅拥有一个独特的被动技能,决定了两张初始大臣卡牌(两张固定视为飞鹰类型的卡牌)在法令区四个列中的初始位置。选定领袖后,飞鹰需要在地图上猫咪城堡斜对角的那个地点,放置一个鸟巢以及六个士兵。</p>
<p>该阵营最为重要的机制有且只有一个:<span class="emphasis">法令</span>。飞鹰的阵营板上有一个分为四个栏位的法令区,从左到右依次为招募、移动、战斗和建造。在每一个单独的列中,如果有两张或以上的卡牌,玩家可以按任意顺序解决该列里的所有牌,但对于每一张牌,玩家都必须切实执行其所在列对应的操作。</p>
<p>招募要求玩家在带有与卡牌类型相符、且已经建有鸟巢的地点上放置一个士兵;移动要求玩家从与卡牌类型相符的地点出发,移动至少一个士兵到其他相邻地点,前提是移动的基础条件可以被满足;战斗要求玩家在带有与卡牌类型相符的地点上,主动发起一场战斗;建造要求玩家在一个被自己占领、卡牌类型相符且当前没有鸟巢的地点上,放置一个新的鸟巢。</p>
<p>这一机制是极其死板的。如果在解决法令的过程中,玩家因为版图局势或者自身资源限制,无法完全执行某一张卡牌对应的一项操作,飞鹰就会立即陷入动乱 —— 当天的白天阶段会被立即强制中止。玩家会因为法令区中包含的每一张飞鹰类型的卡牌而失去 1 分,飞鹰也是唯一一个会在游戏中失去分数的阵营。随后,整个法令区除了两张初始的大臣卡牌外,所有的手牌都会被清空弃置。触发动乱的现任领袖必须下台,玩家需要从备选的领袖中挑选一位接任。新领袖的上台会改变初始卡牌所在的列数位置,玩家也必须在接下来的回合里重新构筑整个行动链条。</p>
<p>如果飞鹰成功且完整地解决了白天的所有法令,便能顺利进入晚上阶段,这也是其核心的得分环节。飞鹰会根据地图上现存的鸟巢总数,直接获取阵营板上对应位置标明的分数。鸟巢铺设得越多,每回合自动获取的分数就越高。计分结束后,飞鹰进行手牌抽取,抽牌的具体数量同样由版图上的鸟巢数量决定。</p>
<p>最后说一下飞鹰的被动技能。作为森林过去的领主,当一个地点上飞鹰的士兵以及建筑物的数量,和其他阵营的士兵以及建筑物的数量,相同时,默认飞鹰占领该领地。飞鹰也藐视贸易,锻造物品时会忽略列出的分数,而只获得 1 分。</p>
<h4 id="森林联盟"><a class="markdownIt-Anchor" href="#森林联盟"></a> 森林联盟</h4>
<p>在猫咪和飞鹰天天打架的时候,森林的老百姓坐不住了…… 联盟需要努力赢得森林里对现状不满的各种动物的同情,大家联合起来,将女侯爵还是王朝都赶出森林!</p>
<p>森林联盟是一个起步极晚但爆发力极强的阵营。与其他阵营不同,联盟在开局阶段的地图上没有任何实质性的棋子,只有阵营板上的 3 个基地、10 个民意令牌以及 10 个士兵。</p>
<p>联盟的运作高度依赖一个独立于玩家手牌的特殊卡牌区域 —— 支持者牌堆。支持者牌堆里的卡牌面朝下放置,不计入手牌上限,只有联盟玩家可以查看,且专门用来执行联盟的核心行动。如果联盟在地图上没有建立任何基地,该牌堆的容量上限仅有 5 张,超出部分必须被直接弃置;而一旦地图上存在至少一个联盟基地,支持者牌堆的容量便没有限制。</p>
<p>联盟拥有两个让其他阵营极为头疼的被动技能。首先是民意机制。每当其他玩家移除了地图上的民意令牌,或者将任何士兵移动到一个有民意的地点时,该玩家必须从自己的手牌中强制上交一张与该地点类型相符的卡牌,并将其加入联盟的支持者牌堆。如果该玩家手中没有对应类型的卡牌或者飞鹰卡牌,则必须向联盟玩家展示手牌自证,随后联盟会从公共牌堆顶部抽取一张牌加入支持者牌堆。</p>
<p>另一个被动技能是「游击战」。这是整个 Root 游戏中,强度最为可怕的被动技能:在所有战斗中,只要联盟是作为防守方被攻击,那么联盟始终会拿取点数较大的骰子作为自己的命中数,而攻击方只能拿取较小的骰子。这意味着主动攻击联盟很多时候只会被联盟反杀。</p>
<p>既然提到了骰子,我想要再深入讲解一下 Root 骰子的机制。已知每枚骰子有四个面,点数是 0/1/2/3,因此投掷结果是由两枚骰子组成的 16 种等概率组合构成的样本空间。在这个样本空间中,取最大值的概率分布是不均匀的。两枚骰子最大值为 0 的组合仅有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mn>0</mn><mo separator="true">,</mo><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(0,0)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span></span> 这一种,概率为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mi mathvariant="normal">/</mi><mn>16</mn></mrow><annotation encoding="application/x-tex">1/16</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord">/</span><span class="mord">1</span><span class="mord">6</span></span></span></span>;最大值为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span> 的组合有 3 种,概率为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>3</mn><mi mathvariant="normal">/</mi><mn>16</mn></mrow><annotation encoding="application/x-tex">3/16</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">3</span><span class="mord">/</span><span class="mord">1</span><span class="mord">6</span></span></span></span>;最大值为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn></mrow><annotation encoding="application/x-tex">2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">2</span></span></span></span> 的组合有 5 种,概率为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>5</mn><mi mathvariant="normal">/</mi><mn>16</mn></mrow><annotation encoding="application/x-tex">5/16</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">5</span><span class="mord">/</span><span class="mord">1</span><span class="mord">6</span></span></span></span>;而最大值为 3 的组合最多,共有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>7</mn></mrow><annotation encoding="application/x-tex">7</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">7</span></span></span></span> 种,概率为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>7</mn><mi mathvariant="normal">/</mi><mn>16</mn></mrow><annotation encoding="application/x-tex">7/16</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">7</span><span class="mord">/</span><span class="mord">1</span><span class="mord">6</span></span></span></span></p>
<p>也就是说,掷出 2 点和 3 点的概率加在一起,正好是 75%。如果计算较大值的数学期望,就会是 2.125,而较小值的数学期望仅为 0.875。在基础规则下,主动进攻方有着绝对的火力优势,然而「游击战」强制反转了这一判定规则。只要森林联盟作为防守方被攻击,从概率论的角度来看,这一反转让攻击方的单次命中期望瞬间从 2.125 骤降直 0.875,而联盟的防守反击期望则从 0.875 飙升至 2.125。</p>
<p>清晨阶段是联盟扩张与爆发的核心时间段,分为「起义」和「散播民意」两步。</p>
<p>起义是联盟建立基地的唯一方式,玩家需要选择一个已有民意令牌且类型与阵营板上未建基地相符的地点,随后从支持者牌堆中消耗两张匹配该地点类型的卡牌。起义一旦爆发,该地点上的所有敌方棋子,包括士兵、建筑物和各种令牌,将被瞬间<span class="emphasis">全部</span>清空(联盟也会获取摧毁建筑物和令牌所得的分数)。接着,联盟会在该地点放置对应的基地,并根据目前地图上与该基地类型相符的民意令牌总数,放置等量的士兵,最后再将一名士兵放置到阵营板的教官区。</p>
<p>执行完起义后,联盟可以进行散播民意来获取分数。玩家必须选择一个与现有民意地点相邻的无民意地点(若地图上完全没有民意,则可任选地点)。根据民意令牌轨道上标明的成本,玩家需要从支持者牌堆中消耗对应数量且与目标地点类型匹配的卡牌,将民意放置上去并立即获得轨道上显示的分数。</p>
<p>需要注意的是戒严规则:如果目标地点内驻扎着至少三名属于同一敌方阵营的士兵,联盟在传播民意时必须额外多消耗一张匹配的支持者卡牌。</p>
<p>白天阶段,联盟可以进行手牌和支持者牌堆的资源转化。联盟可以执行动员,将手中的任意卡牌放入支持者牌堆中。同时也可以执行训练,通过消耗手中一张与地图上已有联盟基地类型相匹配的卡牌,将一名士兵放置到教官区。必须要注意的是,联盟只有 10 个士兵,放置多少个到教官区、保留多少个士兵在地图上,是游玩联盟阵营时必须要考虑到的问题。此外,联盟的卡牌锻造也在白天阶段进行,与其他阵营依赖特定的建筑物不同,联盟是通过激活地图上对应类型的民意令牌来完成锻造的。</p>
<p>夜晚阶段则是联盟进行常规版图互动的时刻。联盟可以根据阵营板上现有的教官数量,执行同等次数的军事行动。军事行动包含四种选项:移动士兵、发起战斗、在拥有基地的地点招募一名士兵,或是执行组织行动。组织行动允许联盟从一个没有民意的地点移除一名自己的士兵,并直接在那里放置一个民意以此获取分数,这是一种不消耗支持者卡牌来传播民意的方式。</p>
<p>在所有军事行动结束后,联盟进行常规的抽取手牌步骤,并将超出五张上限的多余手牌弃置。每次基地被敌人摧毁时,联盟必须丢弃支持者牌堆中所有与该基地同类型的卡牌,并损失一半的教官(向上约)。</p>
<h4 id="神秘游侠"><a class="markdownIt-Anchor" href="#神秘游侠"></a> 神秘游侠</h4>
<p>在猫咪、飞鹰和联盟互相牵制的期间,森林里总有一些流浪者,想要趁机提升自己在森林中的声望 —— 这当然也包括了恶名。与那三个势力截然不同的是,游侠在地图上只有一个棋子,那就是游侠自己。游侠并不属于士兵,因此永远无法占领任何地点,也无法阻止其他阵营占领地点,且无法被移除。但这种孤立也赋予了游侠移动时可以完全无视出发地和目的地的占领权限制。</p>
<p>游侠的行动与生存完全依赖于他的物品系统。无论是移动、战斗、探索废墟获取新装备,还是完成任务与援助他人,都需要消耗背包或物品栏中对应的、未损坏的物品。</p>
<p>这里需要提到 Root 的物品系统。物品可以通过锻造特定的卡牌来获取,对于不会用到物品的阵营来说,锻造出来的物品只会从公共物品区取出一个、放到一边。当公共物品区里没有物品了,那么制造物品的卡牌便无法被锻造,自然也不能用来锻造得分。</p>
<p>而对于会使用到物品的阵营来说,物品还可以通过地图上的废墟来获取。游侠能够探索这些废墟、获取废墟内的物品,并且将废墟移除、变成一个空的建筑物格子。如果本局游戏里没有能够移除废墟格子的阵营,那么这些废墟格子会一直占着空闲的建筑物格子。</p>
<p>对游侠来说,物品具有两个通用的属性:是否被使用,以及是否损坏。这两个属性是<span class="emphasis">完全独立</span>的。在遭遇战中,由于游侠没有士兵可供阵亡,他所拥有的未损坏物品总量便等同于他的生命值上限,而未损坏的物品「剑」的总数,等同于能够掷出的最大命中数,无论是否被使用。每当游侠受到一点伤害,他就必须将一件未损坏的物品移入损坏区。如果身上没有任何完好的物品,游侠则忽略所有剩余的伤害。</p>
<p>处理与其他阵营的社交关系是游侠核心的战略维度。通过消耗物品并向其他玩家支付对应地点类型的卡牌,游侠可以执行「援助」行动。这不仅能从其他玩家那里换取他们锻造好的物品,还能逐步提升双方的关系轨道。当关系达到同盟状态时,游侠便赢得了该阵营的信任,不仅每次援助都能获得额外分数,还能在白天行动时直接裹挟盟友的士兵一同移动甚至发起进攻。</p>
<p>反之,如果游侠在游戏中移除了任何一个非敌对阵营的士兵,双方的关系会立刻跌入敌对状态。虽然游侠进入有敌对士兵驻扎的地点时需要额外消耗用于移动的物品,但这开启了另一条得分途径:在游侠自己的回合内,每在战斗中移除一个敌对阵营的部件(无论士兵、建筑还是令牌),游侠都能获得 1 分。这种得分机制太可怕,以至于官方需要在比赛中特别削弱游侠,才能平衡游戏。</p>
<p>游侠的开局阶段中,玩家需要选择一个游侠角色。不同的游侠角色开局携带的物品不同,且技能也都不一样。接着玩家需要将游侠米宝放置在森林里,注意,并不是在地图的格子内,而是其他阵营都无法进入的「森林」里。然后玩家会获取一个任务牌堆,抽取 3 张、面朝上放在阵营板的附近。任务需要游侠到达任务牌上类型相符的地点,并使用任务所需要的未使用物品,以获取奖励:得分或者抽卡。随着同类型的任务做得越来越多,得分以及抽卡的数量也会越来越多。不过在我看来,靠任务得分并不是一个很棒的选择。</p>
<p>清晨阶段,3 个已使用的物品会变成未使用状态,且每有 1 个物品「水壶」,还可以多刷新 2 个物品。接着游侠可以无消耗地移动到相邻的地点或者森林中,无论该地点是否被敌对阵营占领。</p>
<p>早上阶段,游侠可以按照任意顺序来使用自己的物品:</p>
<ul>
<li>移动:使用 1 个物品「靴子」;</li>
<li>战斗:使用 1 个物品「剑」;</li>
<li>探索:使用 1 个物品「火把」,探索后获得 1 分;</li>
<li>援助:使用任意 1 个物品。就算是敌对阵营,游侠也可以援助,但是关系不会变好;</li>
<li>任务:使用任务牌上所要求的物品;</li>
<li>打击:使用 1 个物品「弩」,直接移动当前所在地点的士兵或者建筑物或者令牌。打击并不算战斗,但是算移除士兵或者令牌,因此不会触发游侠杀害士兵得分的机制,但是会触发联盟民意被移除的机制;</li>
<li>制作:选中一张手牌,在类型相符的地点上使用 1 个物品「锤子」来锻造它。因为游侠只能一次出现在一个地点上,意味着所有要求多个地点类型的卡牌都无法被锻造;</li>
<li>修复:使用 1 个物品「锤子」,将一个已损坏的物品变成未损坏的状态。不过如果该物品也出于已使用的状态,那么修复并不会让它也变成未使用的状态;</li>
<li>特殊行动:游侠角色的技能不同,在进行的特殊行动也不同,不过使用的都是物品「火把」。例如「猎人」角色就可以一次性修复 3 个物品,代价是白天阶段会被立即结束。</li>
</ul>
<p>晚上阶段中,如果游侠处于森林,那么所有已使用或者已损坏的物品都会变成未使用或者未损坏的物品,相当变态。接着抽取卡牌,每有 1 个物品「金币」都会额外抽取 1 张。若手牌多于 5 张,则丢弃手牌直到手牌数为 5 张。最后,游侠要检查物品的容量。如果未损坏和已损坏的物品总数超过物品上限(默认 6,每有 1 个物品「背包」便多出 2),那就需要丢弃物品,直到物品数量等于物品上限。这里的「丢弃」并不代表着将物品放回公共物品区,被丢弃的物品不会再回来。</p>
<h3 id="结语"><a class="markdownIt-Anchor" href="#结语"></a> 结语</h3>
<p>本篇文章仅供参考。在实际的游玩时,我建议还是阅读官方提供的规则书,或者说 <a target="_blank" rel="noopener" href="http://root.livingrules.io/">这个网站</a>。为了减少篇幅,我没有细讲许多内容,只是将游戏的大致规则讲了一遍。</p>
<p>Root 除了实体桌游外,还有电子版本。你可以从 Steam 上购买下载,也可以在 Google Play 或者 App Store 中购买下载。购买游戏本体是不共通的,但是购买 DLC 是可以通过 Dire Wolf 账户实现共通。</p>
<p>又因为 Root 既有实体桌游,也有电子版本,我采取的讲述方式是同时基于了它们二者:你会发现我尽量不去介绍桌游特有的实体物件,也没有无视掉电子版本中程序已经帮助玩家处理好的地方,而是围绕着游戏机制本身进行介绍。</p>
<p>未来我考虑继续介绍 Root 的 DLC 内的阵营,或者说阵营的进阶玩法。</p>
</body></html></div></article></div></main><footer><div class="paginator"><a class="prev" href="cf35.html">上一篇</a><a class="next" href="9408.html">下一篇</a></div><!-- Webmention 显示区域--><div class="webmention-section" data-page-url="posts/cc52.html" data-full-url="https://cytrogen.icu/posts/cc52.html" data-mode="static">
                <h3 class="webmention-title">Webmentions (<span class="webmention-count">1</span>)</h3><div class="webmention-group webmention-group-likes"><h4 class="webmention-group-title">喜欢 (1)</h4><div class="webmention-compact-list"><div class="webmention-compact-item"><img class="webmention-compact-photo" src="https://avatars.webmention.io/media.otter.homes/b3a5ebdc7764c92d0a28a39ee05451f98685bd5f10185dc981856443952aa13c.png" alt="KipJayChou ⁂" loading="lazy"><a class="webmention-compact-name" href="https://mstdn.feddit.social/@admin" target="_blank" rel="noopener ugc">KipJayChou ⁂</a></div></div></div></div><div class="copyright"><p class="footer-links"><a href="../friends/index.html">友链</a><span class="footer-separator"> ·</span><a href="../links/index.html">邻邦</a><span class="footer-separator"> ·</span><a href="../contact/index.html">联络</a><span class="footer-separator"> ·</span><a href="../colophon/index.html">营造记</a><span class="footer-separator"> ·</span><a href="../atom.xml">RSS订阅</a></p><p>© 2025 - 2026 <a href="https://cytrogen.icu">Cytrogen</a>, powered by <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/cytrogen/hexo-theme-ares" target="_blank">hexo-theme-ares</a>.</p><p><a href="https://blogscn.fun" target="_blank" rel="noopener">BLOGS·CN</a></p></div></footer></div></div><a class="back-to-top" href="#top" aria-label="返回顶部"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M3.293 9.707a1 1 0 010-1.414L9.586 2a2 2 0 012.828 0l6.293 6.293a1 1 0 01-1.414 1.414L11 3.414V17a1 1 0 11-2 0V3.414L2.707 9.707a1 1 0 01-1.414 0z"></path></svg></a><script>document.addEventListener('DOMContentLoaded', function() {
  const codeBlocks = document.querySelectorAll('figure.highlight');
  
  codeBlocks.forEach(block => {
    let caption = block.querySelector('figcaption');
    if (!caption) {
      caption = document.createElement('figcaption');
      block.insertBefore(caption, block.firstChild);
    }

    const info = document.createElement('div');
    info.className = 'info';
    
    const filename = caption.querySelector('span');
    if (filename) {
      filename.className = 'filename';
      info.appendChild(filename);
    }
    
    const lang = block.className.split(' ')[1];
    if (lang) {
      const langSpan = document.createElement('span');
      langSpan.className = 'lang-name';
      langSpan.textContent = lang;
      info.appendChild(langSpan);
    }

    const sourceLink = caption.querySelector('a');
    if (sourceLink) {
      sourceLink.className = 'source-link';
      info.appendChild(sourceLink);
    }

    const actions = document.createElement('div');
    actions.className = 'actions';

    const codeHeight = block.scrollHeight;
    const threshold = 300;

    if (codeHeight > threshold) {
      block.classList.add('folded');
      
      const toggleBtn = document.createElement('button');
      toggleBtn.textContent = '展开';
      toggleBtn.addEventListener('click', () => {
        block.classList.toggle('folded');
        toggleBtn.textContent = block.classList.contains('folded') ? '展开' : '折叠';
      });
      actions.appendChild(toggleBtn);
    }

    const copyBtn = document.createElement('button');
    copyBtn.textContent = '复制';
    copyBtn.addEventListener('click', async () => {
      const codeLines = block.querySelectorAll('.code .line');
      const code = Array.from(codeLines)
        .map(line => line.textContent)
        .join('\n')
        .replace(/\n\n/g, '\n');
      
      try {
        await navigator.clipboard.writeText(code);
        copyBtn.textContent = '已复制';
        copyBtn.classList.add('copied');
        
        setTimeout(() => {
          copyBtn.textContent = '复制';
          copyBtn.classList.remove('copied');
        }, 3000);
      } catch (err) {
        console.error('复制失败:', err);
        copyBtn.textContent = '复制失败';
        
        setTimeout(() => {
          copyBtn.textContent = '复制';
        }, 3000);
      }
    });
    actions.appendChild(copyBtn);

    caption.innerHTML = '';
    caption.appendChild(info);
    caption.appendChild(actions);

    const markedLines = block.getAttribute('data-marked-lines');
    if (markedLines) {
      const lines = markedLines.split(',');
      lines.forEach(range => {
        if (range.includes('-')) {
          const [start, end] = range.split('-').map(Number);
          for (let i = start; i <= end; i++) {
            const line = block.querySelector(`.line-${i}`);
            if (line) line.classList.add('marked');
          }
        } else {
          const line = block.querySelector(`.line-${range}`);
          if (line) line.classList.add('marked');
        }
      });
    }
  });
});</script><script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script><script>(function() {
  document.addEventListener('DOMContentLoaded', function() {
    const themeToggle = document.querySelector('.theme-toggle');
    
    if (!themeToggle) return;
    
    const getCurrentTheme = () => {
      return document.documentElement.getAttribute('data-theme') || 'light';
    };
    
    const updateUI = (theme) => {
      const isDark = theme === 'dark';
      themeToggle.setAttribute('aria-pressed', isDark.toString());
    };
    
    const setTheme = (theme) => {
      document.documentElement.setAttribute('data-theme', theme);
      document.documentElement.style.colorScheme = theme;
      
      const pageWrapper = document.getElementById('page-wrapper');
      if (pageWrapper) {
        pageWrapper.setAttribute('data-theme', theme);
      }
      
      // Find and remove the temporary anti-flicker style tag if it exists.
      // This ensures the main stylesheet takes full control after the initial load.
      const antiFlickerStyle = document.getElementById('anti-flicker-style');
      if (antiFlickerStyle) {
        antiFlickerStyle.remove();
      }
      
      localStorage.setItem('theme', theme);
      updateUI(theme);
    };
    
    const toggleTheme = () => {
      const current = getCurrentTheme();
      const newTheme = current === 'light' ? 'dark' : 'light';
      setTheme(newTheme);
    };
    
    updateUI(getCurrentTheme());
    
    themeToggle.addEventListener('click', toggleTheme);
    
    if (window.matchMedia) {
      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
      mediaQuery.addEventListener('change', function(e) {
        if (!localStorage.getItem('theme')) {
          const theme = e.matches ? 'dark' : 'light';
          setTheme(theme);
        }
      });
    }
  });
})();
</script><script src="../js/details-toggle.js" defer></script><script>(function() {
  document.addEventListener('DOMContentLoaded', function() {
    const backToTopBtn = document.querySelector('.back-to-top');
    
    if (!backToTopBtn) return;
    
    const toggleButtonVisibility = () => {
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
      const shouldShow = scrollTop > 200;
      
      if (shouldShow) {
        backToTopBtn.classList.add('is-visible');
      } else {
        backToTopBtn.classList.remove('is-visible');
      }
    };
    
    let ticking = false;
    const handleScroll = () => {
      if (!ticking) {
        requestAnimationFrame(() => {
          toggleButtonVisibility();
          ticking = false;
        });
        ticking = true;
      }
    };
    
    const scrollToTop = (event) => {
      event.preventDefault();
      window.scrollTo({
        top: 0,
        behavior: 'smooth'
      });
    };
    
    window.addEventListener('scroll', handleScroll);
    backToTopBtn.addEventListener('click', scrollToTop);
    
    toggleButtonVisibility();
  });
})();</script></body></html>