« November 2025 | Main | January 2026 »

December 23, 2025

Skynet 升级到 Lua 5.5.0

Lua 5.5.0 已经正式发布。所以,skynet 的 Lua 版本也随之升级。

skynet 维护了一份修改版的 Lua ,允许在多个虚拟机之间共享函数原型。这可以节省初始化 Lua 服务的时间,减少内存占用。

跨虚拟机共享函数原型最困难的部分是函数原型会引用常量字符串,而 Lua 在处理短字符串时,需要在虚拟机内部做 interning 。所以 skynet 的这个 patch 主要解决的是正确处理被 interning 的短字符串和从外部导入的函数原型中包含的字符串共存的问题。具体方法记录在这篇 blog 中

这个 patch 的副产品是允许在多个 Lua VM 间共享常量表。打了这个 patch 后,就可以使用 skynet.sharetable 这个库共享只读常量表了。

这次 Lua 5.5 的更新引入了 external strings 这个特性,已经大幅度提升了 Lua 加载字节码的速度。我比较倾向于在未来不再依赖额外的 patch 减少维护成本。所以建议新项目避免再使用共享常量表,减少对 patch 过的 Lua 版本的依赖。


Lua 5.5 基本上兼容 Lua 5.4 ,我认为绝大多数 skynet 项目都不需要特别改动。但在升级后,还是建议充分测试。注意:更新仓库后,需要用 make cleanall 清除 lua 的编译中间文件,强制 Lua 重新编译。直接 make clean 并不清理它们。

Lua 5.5 有几处更新我认为值得升级:

  1. 增加了 global 关键字。对减少拼写错误引起的 bug 很有帮助。skynet 自身代码暂时还没有使用,但后续会逐步添加。

  2. 分代 GC 的主流程改为步进式进行。过去版本如果采用分代模式,对于内存占用较大的服务,容易造成停顿。所以这类服务往往需要切换为步进模式。升级到 Lua 5.5 后,应该就不需要了。

  3. 新的不定长参数语法 ...args 可以用 table 形式访问不定长参数列表。以后可以简化一部分 skynet 中 Lua 代码的实现。

December 16, 2025

带可可学数学

可可三年级,前段老师说她数学成绩不好,需要在家加强一下。

这段时间我每天晚上给她讲一点点数学,都是课本上的内容,然后我再稍稍发挥一下。几次之后,我发现最大的问题是她觉得数学很无聊。

她似乎比较抗拒学新的知识,更喜欢用熟悉的方法。去年我发现她计算能力有问题,每天给她做加减法练习,总算不再用更早年我教她的 +1 法算加法了:即计算 7+8 的时候,算 8 次 +1 ,也就是数数。二年级学了乘法,乘法表也背了,但现在做应用题,本该用乘法的场合,她还是习惯连续算加法,一旦乘数太大就会出错。要用除法的时候就更混乱了,并不是用减法,而是靠猜测来试。大脑里完全没有建立乘除的概念。乘法表更像是独立的有背诵任务的诗词,还没古诗那么有趣。

我说:数学其实是这个世界上最有趣的东西。

她说:为什么呢?

我说:这个世界上有趣的东西很多,但数学是性价比最高的。一本数学书很便宜,但可以让你读很久。从中发现有那么多有趣的事实。原来解决不了的问题,知道方法突然就明白了。如果是自己找到的方法,就更让人兴奋了。

她说:我还是觉得数学没意思。

我说:慢慢来,不着急。首先不要排斥它。学数学其实不需要硬背那么多东西,我小时候最不喜欢背书了,所以才喜欢数学的。因为数学是最不需要背的,只要你从原理出发,一步步理解,最后什么问题都能解决,只是速度慢一点。多练习就快了。那些需要记住的知识,用的多就自动记住了,不需要专门背。


还好她不排斥我给她讲数学。前段还给我说,为什么只有你给我讲数学我才懂呢?

就这么,我每天(半个小时左右)给她讲一点点。我觉得其实也讲不了什么,聊胜于无。有一点我觉得还不错,她有数学作业不会做,会主动来问,不需要等我检查作业。一点拨就懂了,但第二天又会有新问题,依旧靠自己解决不了。不过,知道自己不懂算是个好的开始吧?

昨天晚上,她说今天学的直线、射线和线段。这个好简单,之前的都好难。

我说,我出道题目吧。在纸上画五个点,你看看一共可以连出多少条线段。

她说,我去拿张纸来。

画了半天,数错了。可可说,我脑子好乱啊。

我说,我来教你方法。我们先把你画的点标上数字编号,从 1 标到 5 。然后你每次连一条线段,就把两端的数字记在图案下方,顺着写整齐。最后,数下面的记号。

这次她算对了。但是,好麻烦啊,为什么要用这么麻烦的方法。我想偷懒就会搞错。

我说,其实,你不需要画图,只用写数字就可以了。但是不要随便连线。1 号点先和 2 号点连,再和 3 号点连…… 顺着数字从小到大,这样就不会搞错。不需要真的把连线图画在纸上,在脑子里相像就可以了,只需要在纸上写下 1 号点能和几个点连成线段就可以了。这里,你写个 4 。然后再看 2 号点。

她画了一点时间,终于发现了规律,列出了算式 4 + 3 + 2 + 1 = 10 。

我说看吧,其实这不是一道绘图题,用数学方法,它转化为一道计算题了。

可可好像有点兴趣了,说我现在可厉害了,我能算 10 个点的问题。我说你试试。可可的悟性没我相像的那么高,并没有直接写出 9 到 1 的等差数列,每个数字都想了一会,直到 4 以后才有点把握后面应该是 3 2 1 。但是,面对长达 10 个数字的加法算式,可可说,我知道方法了,这个算起来太麻烦了,我不算了。

我说,你不是学了乘法吗?其实,这个问题不一定要用加法做,我告诉你怎么用乘法解决这个问题,就不用算这么麻烦的算式了。你看,刚才你连线的时候,把 1 号和 2 号连起来之后,从 2 号做起点就不连 1 号了。因为 1 到 2 和 2 到 1 是同一条线段。两个点之间只可以连一次。但是,如果我们每两个点都连两次,那么这 10 个点,每个都可以连出去 9 条(射线)。

最后,总共画了 10 组,每组 9 条射线,一共是 10 * 9 = 90 条。因为我们每条线段都计算了 2 次,所以答案就是 90 / 2 = 45 条线段。

有了这个方法,100 个点的问题你也能算出来了吧。

可可问,家里有没有有趣一点的数学书,我要看。我翻出了前年带着云豆读过的《我的第一本数学书》。可可翻了一下说,怎么这么多字啊。我说,周末我带着你读。


早上起床的时候,可可问,今天我能不能把昨天那本书带到学校去?

希望她能发现一点点数学的乐趣。

December 15, 2025

最近玩的几款卡牌构筑类电子游戏

最近玩了几个卡牌构筑类的电子游戏,觉得颇为有趣,值得记录一下。

首先是 Decktamer(训牌师)。我玩了十几个小时,把初级难度通关了。

它的新设计是用卡牌构筑的形式重新做了一个宝可梦。和杀戮尖塔开创的战斗结束后抽卡,用战斗胜利的奖励钱买卡、洗卡、升级的模式不同。它的战斗卡是不需要洗的,战斗中死亡就直接消失;新卡片是在战斗中捕获对手获得。加强战斗卡的方式主要是用道具卡杂交战斗卡:从一张战斗卡上抽取需要的技能,加到另一张战斗卡上。

战斗过程更像是万智牌那种更传统的卡牌战斗模式:摆放战斗卡都场上,再由上场的卡片发动能力。这种传统战斗模式不同,发动战斗技能没有额外的资源消耗,而修改成每回合必然从卡片上所有技能中选择一个。这可以避免给同一张卡片合成太多能力造成的不平衡。更多能力往往只是增加了容错性,可以应付更多场景。

玩家卡牌被分成了两个牌堆:战斗卡堆和道具卡堆。这种双卡堆的模式最近的卡牌构筑游戏中比较常见,下面还会再提到。不过这里道具卡堆并不是抽牌堆,更像是一个道具背包,可以随时使用。

我在简单难度通关的感受是:只有最终 boss 有挑战。而这种挑战更像是一个谜题。所以第一次面对最终 boss 我没有一次通过。而是熟悉了它的技能,第二次刻意针对这些技能来升级牌组,这样才通关。整个游戏给我的感觉是,解密成分更重一些,也就是该如何养卡才能解决对手。所以游戏里(简单模式下)有无限次的 undo 。我相信选择更高难度后会有不同的感受。不过暂时没有玩下去。


第二个游戏是 Rogue Hex 。大约玩了 7 个小时,四个设计角色中,前三个获得了胜利。

这个游戏用卡牌构筑的形式重新实现了一个简化版的文明。这是我之前就特别想做,但是没想到合适方案的点子。所以,我在初玩时感觉相当有趣。能把卡牌构筑的乐趣融合到 4x 游戏中相当不错。不过,玩到游戏后期,数值还是有点崩,往往中盘就几乎碾压对手了,但为了胜利,依旧需要机械性的玩很多回合。

当然,我觉得它的核心机制设计的还是挺好的。这是个新游戏,平衡还有很大的改善空间。

在这个游戏中,基本资源分别是:劳动力用于抽牌打牌、食物用来发展发展城市、计划用来移动地图单位、信仰用来重置、金钱用来替换前面的基本资源。这些资源有仓储上限,回合结束的时候超过上限的部分会浪费掉。我认为“仓储限制”是让玩家有更多选择的核心设计点之一。

无仓储限制的成长涉及两个点数,科技用于增加正面 buf (类似杀戮尖塔中的神器)以及生产用于增强牌组。我认为设计两个的原因也是给玩家提供选择。大多数情况下,发展科技就会降低生产的增速,反之亦然。

像文明那样,玩家可以在版图上探索采集一次性资源转换为一次性消耗的卡片;扩展城市获得永久资源再用卡牌转换为永久建筑或用版图上的工人单位采集转换为卡片。这部分对文明原本的系统还原的挺不错的(至少在每局游戏的前半段很好)。

游戏循环基本上是用抽牌的手牌积累科技点、生产点和上述的基本资源。用这些点数兑换成发展。和文明一样,指挥地图单位探索和攻击对手也是发展重要的一环。把文明游戏机制中的各种操作翻译为打牌,最大的区别在于:原本玩家可以自由分配每个回合的行动,而在卡牌模式下,需要根据抽到的手牌做决定。这有两个方面的变化:其一、原始机制下提供给玩家的选择非常多,容易产生选择困难;手牌是有限的,玩家可以聚焦在有限行动选择中。其二、可选行动有了随机性,玩家需要根据牌组、抽牌堆、抽牌能力去管理随机性。这也是卡牌构筑类型游戏的核心玩法。

但嫁接卡牌构筑类型和 4x 类型系统有一个需要设计的地方: 4x 游戏中每个回合给玩家的选择都是有意义的,如果把太多东西做成卡牌供玩家选择,而每个回合选择受限,很可能极大的降低游戏的容错性,变得太看脸。所以,在这个游戏中,劳动力即用于支付打牌成本,又可以用来抽牌。这等于提供给玩家一个主动增加选择的能力,而不是像杀戮尖塔中那样,抽牌本身也是特定卡片的技能。

我发现很多类似游戏(下面会再次提到)都有这个设计:允许玩家主动花一个特定资源点,就可以抽牌。

但是,这类游戏成长点太多。不像杀戮尖塔那样只是提高和优化卡组,每局游戏后期很难不崩掉。要么前期开荒死掉,要么后期碾压变得选择没有太大意义。我觉得这个游戏还可以改进,我也很期待会使用怎样的解决方法。


最后一个游戏是 Dawnmaker ,也是最近我最喜欢的一个。我玩了 30 个小时,所有难度都通关了。

这个游戏回答了我很多之前没想到设计解法的问题。它对卡牌构筑类型做了更多的保留,没有卡牌战斗部分,更接近一个生存类型的基地建造游戏。玩这个游戏时让我想到了 retromine 和 Stellar Orphans (星际孤儿)。但很多设计处理的更好。

这个游戏就是打出卡牌在六边形棋盘上建造建筑让基地活下去。没有敌人,无需战斗,需要对抗的只是逐步增加的粮食需求。

单局游戏内只有五种资源:粮食、科技点、工程点、行动点、胜利点。赢得单局游戏可以获得金钱,金钱用来升级卡组,在后续的游戏局种获得优势,以对抗难度逐步上升的挑战。

游戏设定了两个卡堆:手牌堆和市场建筑堆。这两个卡堆分开抽牌。手牌在当前回合打出的工程点可用来在市场堆购买建筑,并在版图上建造。建筑放在版图上就有了持久能力,通常用于配合手牌更有效的获取资源。和 Rogue Hex 不同(它没有双卡堆),购买的建筑卡必须立刻摆在版图上,而不是置入抽牌/弃牌堆。从我游戏的感受看,这是个没有巧妙的改良设计。

星际孤儿也有市场设定,但受传统卡牌构筑规则的影响,还是设计成从市场购买,投入弃牌堆,抽到手牌使用的循环。控制前期卡和后期卡的方式也只是简单的通过市场掉率决定。但在 Dawnmaker 中,通过市场卡分级严格区分了前期卡和后期卡。如果城镇中心没升级到特定等级,对应的卡片也不会在市场上出现。刷市场只需要消耗科技点,这点和 Rogue Hex 用劳动力抽卡异曲同工。但双卡堆设计避免了直接抽行动牌。因为这类游戏中,行动牌和建筑牌本质上是有区别的。Rogue Hex 用一次性消耗卡表达建筑,我觉得是因为没能跳出传统卡牌构筑规则。

在版图上摆建筑是这个游戏的核心玩法。在非卡牌构筑游戏中非常常见,我也见过很多企图和卡牌构筑类型结合的游戏,只有这个我认为结合的最流畅。在星际孤儿中也有四个 slot 用于安装卡片获得永久能力,但只是点缀,而且安装位置并不改变游戏。

Dawnmaker 的建筑摆放相当重要。甚至比构筑行动卡堆更重要。其变化也非常多,留给玩家很大的选择空间。这种在六边形弃牌上填格子的玩法在桌游中很常见,技巧深度和乐趣很有保障。最近几年也有很多电子游戏基于这类玩法,但我觉得更像桌游电子化,而我玩 Dawnmaker 的感觉则更接近电子游戏的体验。

Dawnmaker 在 steam 上有 demo ,有兴趣的同学可以试试。但 demo 只能玩第一个角色,我在正式版本中尝试了另外两个角色,让我惊讶的是,其实三个角色共享同一套完整的卡池。仅仅只是初始卡组不同,但游戏风格差别非常巨大。而且,游戏中并不设常规卡和稀有卡,抽到的概率是一致的。也就是说无论你用那个初始卡组开局,都可能抽到所有卡片,概率是一致的。但玩游戏的感受却并没有那种:我抽到了特定卡以后,游戏就变容易了的感觉。在熟悉了游戏之后,几乎任何卡片搭配都可以玩出花来。

三个初始卡组(角色)标注的是 regular ,complex ,extreme 。我一开始以为是三档难度,通过调整数值减少容错性,需要逐级更熟悉游戏规则才能玩下去。

通关后的感受是:的确越后面的角色需要对游戏更熟悉。但并没有在数值上减少容错性,而是更复杂的角色代表的需要更复杂的卡片 combo 。三个角色玩的体验也很不一样。

虽然在玩第一个角色时,我能感受到不同的流派:用大块农田组合堆砌粮食产能、用主动激活的方式生产粮食、用科技转换粮食等等。胜利点的来源也可以来源于建筑、科技等。但直到我玩第二个角色才发现,靠版图主动技能的组合也可以另成一番景象。而第一个角色更多的思考如何在版图上摆放建筑的位置。第三个角色更是要求不断的拆建建筑,让版图的布局变成动态的。学会这些玩法后,回头在不同角色中也可以实现(因为共享一个大卡池)。

Dawnmaker 的数值调的非常好。每局游戏的生死总是在一线间。尤其是后面的角色更偏重于主动触发版图技能,相比调配行动手牌多了一层选择。有时候看似死局,仔细思考后居然是有解的。同时又需要一点点运气,概率管理原本就是卡牌构筑游戏的核心,在小丑牌中体现得淋漓尽致,Dawnmaker 也有类似的体验。


在游戏规则上,给我的一点启发:

如何把卡牌构筑结合到基地建设类别游戏上?加入版图元素,把建筑卡堆和行动卡堆分离是个不错的设计。

游戏资源种类不需要太多,不需要完全用卡牌表达。传统的卡牌构筑基本规则中,资源点都是靠当前回合的行动手牌生成,不留到下个回合。但建设类游戏的建造资源完全可以跨回合保留积累,但需要强调仓储上限。这样就可以提供给玩家足够的行动选择和组牌的多样性。

非战斗类游戏,可以用不断上升的需求来制造压力。而需求的上升速度可以和玩家的发展规模挂钩。这样玩家就必须在长期发展和短期生存困境上做出抉择。从自己组建的卡堆中抽卡是卡牌构筑类游戏的核心乐趣来源:提供给玩家更丰富的风险管理手段。