你的等级终于有意义了
现在牌桌上的每个座位都能获得经验,第一次升级只需 60 点经验而不是两周的游戏时间,等级还会授予段位和可收集卡片。

通俗版
经验值曾经是一个什么都不做的数字。游戏里没有任何东西以等级为门槛,而且只有对局的获胜者能拿到经验——这意味着每张牌桌上大约三分之二的人打完整局、输掉、看到「本局经验 +0」,然后没有任何理由认为这个数字与自己有关。
现在每个座位都有收获。名次给经验,游戏结束时手上握有的垄断给经验,撑到最后没被淘汰也给经验。获胜依然占绝对优势——一场胜利的价值超过最好的失败结果的两倍——但输得漂亮不再一文不值。
| 你做到了什么 | 经验 |
|---|---|
| 赢得对局 | +200 |
| 第二名 | +50 |
| 第三名 | +30 |
| 第四名及以下 | +15 |
| 结束时持有的每组垄断(最多 3 组) | +10 |
| 撑到最后没有被淘汰 | +20 |
等级曲线围绕这一点重做了。第一次升级现在需要 60 点经验,一局像样的对局就能达到——哪怕是输掉的那种——而以前大约需要十天的游戏量。之后的等级是逐步变贵,而不是一次性变贵。
等级现在还会授予两样东西。你的等级带有一个段位——共 7 级,从「资格赛」到「大师」——显示在个人资料和排行榜上你的名字旁边。而跨过里程碑等级会掉落一张可收集的地产卡:等级 3, 5, 7, 10, 13, 16, 20,此后每 5 级一次。

技术细节
这件事有意思的一半是删掉副本。旧规则——每 500 点经验一级——被手写进了五个数据库迁移和三个 TypeScript 文件,而且它们之间早已产生偏差:测试数据播下的等级,任何一个版本的规则都产生不出来。现在只有一条曲线、一个文件,并在数据库里被精确镜像:
// packages/game-engine/src/progression.ts — one curve, mirrored exactly in SQL
step(L → L+1) = min(60 + 100·(L−1), 1500)
level 2 3 4 5 10 16 17+
xp 60 220 480 840 4,140 11,400 +1,500 each算术刻意只用整数——不开平方根、不用浮点——这样 SQL 与 TypeScript 在每一个边界上都是完全一致而不是近似一致,并且有一个跑在真实数据库上的测试逐值比对二者。两条曲线都是单调递增的,所以重算时没有任何人在排行榜上超过别人。
做这件事的过程中翻出了三个已经上线一段时间、却没有任何测试抓到的缺陷:结算画面的等级条读的是本局奖励而不是你的总量,于是每个等级的每个玩家看到的都是同一条冻在 40% 的进度条;赢下一局短局会被记成失败,因此那些胜利从未推进过任何胜利任务;而在团队模式里,获胜的队友一分也拿不到并被记为落败,因为两名胜者中有一位按行号并不处在第一名。三个都已修复,且每一个都有一个不修就会失败的测试。
