fix(shop): PriceFormula 大购买次数溢出静默塌陷为 1;同步计划文档残留类型名

geometric 曲线在 purchased 较大时(如 n=300,base=60 growth=1.15)raw
虽仍是合法有限 double(约 9.7e19),但已超出 int64 安全范围,roundi()
对此行为未定义/环绕,经 maxi(...,1) 静默塌陷成 1——方向与「买得越多越
贵」相反,且零诊断。仅判断 is_finite(raw) 测不出这种情况(double 本身
溢出为 INF 要到 n≈5077 才发生,晚于 int64 溢出很多),故改为
`not is_finite(raw) or raw > 9.0e15` 双重判据,触发时 push_error 并钳
到统一上限,不再依赖具体常数断言(新增用例只断言单调性与「不再塌陷回
归」)。

同时补齐 docs_dev/plans/2026-07-31-shelf-c-attribute-shop.md:64 遗漏的
`PriceFormula.Curve` → `PriceFormula.PriceCurve` 同步(enum 部分先前已
改,返回类型标注漏改),并全仓复核确认无其它残留。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 11:05:51 +08:00
co-authored by Claude Opus 5
parent 359da9f24f
commit 6aeadb84b8
2 changed files with 11 additions and 1 deletions
@@ -61,7 +61,7 @@ Expected: `Switched to a new branch 'feat/shelf-c-attribute-shop'`
**Interfaces:**
- Consumes: 无(零依赖)
- Produces: `PriceFormula.compute(spec: Dictionary, purchased: int) -> int``PriceFormula.curve_from_string(s: String) -> PriceFormula.Curve``enum PriceCurve { GEOMETRIC, LINEAR, FLAT }`
- Produces: `PriceFormula.compute(spec: Dictionary, purchased: int) -> int``PriceFormula.curve_from_string(s: String) -> PriceFormula.PriceCurve``enum PriceCurve { GEOMETRIC, LINEAR, FLAT }`
> 纯函数,**先写断言、看它失败、再实现**。断言经 `execute_editor_script` 执行(项目无测试框架)。
+10
View File
@@ -42,4 +42,14 @@ static func compute(spec: Dictionary, purchased: int) -> int:
raw = base
_:
raw = base * pow(growth, float(n))
# raw 可能在两个不同的地方失控:pow() 把 double 本身推到 INFn 极大,如 geometric
# n≈5077+),或者 raw 仍是合法有限 double,但早已超出 int64 可安全表示的范围(如
# geometric n=300 时 raw≈9.7e19——finite 但 > INT64_MAX≈9.22e18)。后者 is_finite()
# 测不出来,roundi() 对超范围 float 的行为是未定义/环绕,曾亲测把它环绕成极小/负值,
# 再经 maxi(...,1) 静默塌陷成 1——方向与"买得越多越贵"完全相反。故用同一个安全阈值
# 9.0e15(远小于 INT64_MAX,远超任何合理金币量)同时兼答两种情况。
const _PRICE_CLAMP: float = 9.0e15
if not is_finite(raw) or raw > _PRICE_CLAMP:
push_error("PriceFormula: 价格溢出(base=%f growth=%f purchased=%d),已钳到上限" % [base, growth, n])
raw = _PRICE_CLAMP
return maxi(roundi(raw), 1)