Skip to content

常用函数与曲线 ​

数值设计的基本词汇是「函数形状」:线性、幂、指数、饱和、封顶、阶梯、分段门槛——绝大多数平衡问题都能归约为「选对形状,再定参数」。本章把公式引擎的能力面展开成一份速查 + 曲线库:内置函数逐个给语义,常用曲线逐条给图、给用途、给陷阱。

::: note 图从哪来(程序是唯一事实源) 本章全部曲线图由 crates/sandtable-core/examples/formula_curves.rs 生成:对每条表达式调用真实求值器(formula::compile + Formula::eval)逐点采样,输出 SVG 到 docs/public/formulas/。不手画图——表达式编译不过,生成器直接 panic,文档曲线与求值器能力不可能漂移。改了求值器后重绘:

bash
cargo run -p sandtable-core --example formula_curves

:::

内置函数(7 个) ​

函数参数语义典型用法
min(a, b)2取小min(10, x) 增益封顶
max(a, b)2取大max(1, atk - def) 保底伤害
clamp(x, lo, hi)3截断到区间clamp(x, 0, 100) 硬上限
floor(x)1向下取整floor(x / 10) * 10 档位化
ceil(x)1向上取整资源按整消耗
abs(x)1绝对值距离 abs(a - b)
round(x)1四舍五入(.5 远离零)展示层整数化

边界行为(有界求值,热点路径不 panic):

  • 除以 0、对 0 取模 → 0(仿真高频路径不允许崩溃);
  • 负数的分数次幂(x^0.5 且 x < 0)→ NaN,NaN 参与比较一律为假——曲线定义域含负值时先套 abs 或分段;
  • 未知函数名、参数个数不对,在加载期编译就报错,不进运行期。

运算符 ​

类别运算符备注
算术+ - * / %% 为浮点取模,同样「模 0 → 0」
幂^右结合;是幂不是异或(与 C 系语言不同)
比较== != < <= > >=结果为 1.0 / 0.0,可直接参与算术
逻辑&& || !返回 1.0 / 0.0;不做短路(表达式纯函数无副作用,两侧都会求值)
条件a ? b : c 三元只求值被选中的分支;可嵌套(右结合),用于分段

优先级从低到高:?: → || → && → == != → < <= > >= → + - → * / % → 一元 - ! → ^。即 -x^2 是 -(x^2),复合条件如 a < b && c > d 不用加括号。

能力边界(如实) ​

没有的内置项:exp / log、三角函数、sigmoid / smoothstep、表查找(lookup 不在表达式层)、随机数。想要时的处理:

想要当前写法说明
指数增长1.15^x常数底幂近似,适合短区间;x 大后爆炸,见下图
对数(减速)k * x^0.5 或 k * x / (x + c)幂减速 / 有理饱和,通常就是对数曲线的合格替身
S 形(sigmoid)分段三元逼近只在确需平滑拐点时;多数场景阶梯或分段已够
线性插值a + (b - a) * t本来就是算术,直接写
真正的 exp / log / 表查找不硬凑按07 章「后续扩展」加 builtin,或等脚本层;表达式层堆技巧换来的可读性损失不值得

曲线库 ​

图内标签维持英文(不依赖 CJK 字形的纪律),读图口径看各节说明。

增长形态:线性 / 幂 / 指数 ​

growth curves

表达式形状典型用途陷阱
x线性每级 +N 的基础成长;预算完全可预测长线运营后期激励不足
x^1.5缓幂递增「越往后越贵/越强」的温和版与线性前期几乎重合,玩家感知不到差异
x^2二次递增战力对属性的放大(如伤害 ∝ 攻击²)属性 10 倍 → 输出 100 倍,叠加增益后极易战力爆炸
1.15^x指数(常数底幂)短期增益(≤30 级的 buff/活动)约 x≈58 越过 x^2,之后一路碾压,长线成长禁用;常与 floor/取整配合做「翻倍感」

选型口径:能线性不幂,能幂不指数——指数只留给有明确终止点的短期系统。

收益递减:三种饱和 ​

diminishing returns

表达式形状典型用途陷阱
10 * x^0.5开方减速,无界单调递减但不上限的收益(边际递减仍鼓励堆叠)前期过陡:0→1 的增益约是 9→10 的 6 倍,新手期体感夸张
100 * x / (x + 25)有理式,渐近 100软上限:命中率、减伤、转化率参数 c 就是「半饱和点」(x=c 时恰 50),改 c 等于挪拐点,别再叠系数
100 * (1 - 0.5^x)几何饱和「每级收益减半」的观感;保底概率随次数上升到 99% 后基本躺平,若希望「后期仍有事做」需叠阶梯补偿

三者都满足「投入越多边际越低」,差别在是否有上界、拐点在哪。有上界的两条,拐点参数(c 与底数)是平衡的主要旋钮。

封顶:硬上限 vs 软上限 ​

soft cap

表达式形状典型用途陷阱
clamp(x, 0, 100)硬上限,超线全蒸发合法值域兜底;命中率/暴击率封顶超线投入零回报,玩家会精确堆到 100 就停——如果希望「继续堆仍有意义」就别用它
x < 50 ? x : 50 + (x - 50) * 0.5拐点折减,超线减半计软上限:仍鼓励堆叠,不惩罚过头斜率 0.5 是第二旋钮;多段折减可嵌套三元,但超过两段就该考虑换形状

口径:砍收益用 clamp,保体验用折减。图上虚线是未封顶参考线,封顶的意义就是让它离开对角线。

量化阶梯 ​

tier ladder

表达式形状典型用途陷阱
floor(x / 10) * 1010 级一档的台阶档位制(段位、品质、副本难度)档位边界处投入无即时回报(「9 级白升」),需配进度展示或下一档预告;虚线参考线与台阶的差就是「沉没投入」
round(x / 10) * 10就近取档四舍五入版,边界观感更匀上下半档不对称浮动,配结算系统时注意可复现口径

分段门槛 ​

threshold bracket

表达式形状典型用途陷阱
x < 30 ? 0 : (x < 60 ? (x - 30) * 2 : 120)门槛-线性-跳档三段:30 前为 0,30-60 线性到 58,60 起跳档至 120 并封顶通行证、赛季任务、解锁制收益门槛前全灰是最伤留存的段,常配保底起始值或首达奖励;斜率 2 是「补偿期追赶速度」旋钮

嵌套三元是本引擎表达分段的标准写法:条件从左往右排,值放分支里。段数 ≥ 4 时可读性明显下降,优先考虑是否真需要这么多段。

组合模式 ​

实际公式几乎都是上述形状的复合,两个高频配方:

text
战力/伤害(前期陡、后期封):min(cap, base * x^1.5)
带门槛的饱和收益:100 * max(0, x - 20) / (max(0, x - 20) + 25)

调参口诀:先定形状,再定参数;每个参数只干一件事(系数管整体幅度,幂次/底数管弯曲,clamp/门槛管边界)。调「手感」时一次只动一个旋钮,否则曲线族变化无法归因——这与参数扫描的 OAT 方法是同一条纪律。

与其他系统的边界 ​

  • 公式层是确定性纯函数:同样输入必得同样输出,随机一律走带键 RNG,不进公式;
  • 加权掉落表、保底、正态分布等概率设施在24 章的专门系统里(model.loot 等),不在表达式层;
  • 公式在加载期编译为 AST,按变量索引求值,无字符串查找——性能口径见07 章执行模型节。

以 Apache-2.0 许可证发布