feat(pool): 迭代20 T2 池结构案D 换代(专长实装批 A段二)

四级档位:TIERS common/excellent/rare/legendary(跨层框架档名映射承袭)——TIER_QUOTAS
70/25/3/0=98 直映射零偏离已裁结构锚(传说=头奖位留空);配额/件值字段物理改名
(旧 rare→excellent、旧 rarest→rare)+凭证四 kind 占位(rap/attune_battery/time_sand/
perfect_insurance,配额暂 0=T4 落路由同批投放)。

概率与上限解耦(案②令牌池+提前退役):curio_cap_* 每 kind 独立字段(99=无上限占位,
实数归调参批)+专长 cap 行字段面;taken 身份维计数(relic:<feat_id>)拿了才计刷出不计;
cap 满在候选视图剔除(牌库本体不动=概率位独立存活);断点 bonus_taken 身份维键随档还原。

曝光槽:三选一=2 格全池+1 格优秀档以上子池(子池独立洗牌同 stream 续消费;子池空回退
全池;池空直通同族兜底);凭证(feat_ticket)不进抽签池只经保底注入;商店货架同 cap 过滤。

潜伏缺陷修正:效果引擎 has 算子 null 安全(敌技伤害载荷无 terrain_kind 事实回落 null 时
判「不在场」而非 String(null) 抛错——候选流变化后 devour 件首次被持有而暴露)。

测试:pool_case_d_test 新套(V6 令牌三态/V7 曝光槽回退/V8 解耦提前退役)入 run_all 20 套;
smoke 三档锚/数值对/池构成/上限带四处断言换代(V14),冒烟 848/0+probe_gate --click 全绿。
This commit is contained in:
DKChan committed 2026-10-11 23:18:35 +08:00
1 parent a57489e970
commit 0640b0c06d
10 files changed
+384 -103

No files matched your search

+5 -3
View File
@@ -277,7 +277,7 @@ static func _on_adventure_bonus(payload: Dictionary, st: Dictionary, adr) -> voi
st.result = "advance_failed"
# 三选一确定性选件(TP0 316-f——1 级优先度=最稀有〔档位最高 rarest>rare>common〕、2 级=最左;
# 三选一确定性选件(TP0 316-f——1 级优先度=最稀有〔迭代 20 四级:legendary>rare>excellent>common〕、2 级=最左;
# 候选并列同档取最左=稳定序保证。空候选/未知档位 = 回退最左防御口径。
# 成型画像(迭代 12 T7——relic 模式 on:候选含 relic 令牌时优先在 relic 集内按 316-f 择一
# 〔贪心捕捞→特性入局→成型画像全流派覆盖——R3 乙单锚承载〕;off=relic 与属性加成型特性同规则竞争)
@@ -296,9 +296,11 @@ static func _pick_token(candidates: Array, feat_mode: String = "off") -> Diction
var t: Dictionary = tok as Dictionary
var rank := 0
match String(t.get("tier", "")):
"rarest":
rank = 3
"legendary":
rank = 4
"rare":
rank = 3
"excellent":
rank = 2
"common":
rank = 1
+19 -17
View File
@@ -218,15 +218,17 @@ func _smoke_adventure_table() -> void:
"clear_heal_pct ∈ [0,100](%d——通关部分回血比例)" % int(_db.adventure.clear_heal_pct))
for tier in _db.adventure.TIERS:
check(int(_db.adventure.tier_total(tier)) == int(_db.adventure.TIER_QUOTAS[tier]),
"档位配额结构锚(v2.2 追认 b):%s = %d 张" % [tier, int(_db.adventure.TIER_QUOTAS[tier])])
check(int(_db.adventure.deck_total()) == 98, "令牌池总量 = 98 张(普通 70/稀有 25/罕见 3——罕见档随道具件池种退役收窄)")
check(int(_db.adventure.curio_value("gp", "common")) == 20 and int(_db.adventure.curio_value("gp", "rare")) == 50
and int(_db.adventure.curio_value("attack", "common")) == 1 and int(_db.adventure.curio_value("attack", "rare")) == 2
and int(_db.adventure.curio_value("max_hp", "common")) == 5 and int(_db.adventure.curio_value("max_hp", "rare")) == 10
and int(_db.adventure.curio_value("armor", "common")) == 1 and int(_db.adventure.curio_value("armor", "rare")) == 2,
"数值对(v2.2):小GP 20/大GP 50 · 小增伤 +1/大 +2 · 小生命 +5/大 +10 · 小护甲 +1/大 +2")
check(int(_db.adventure.curio_value("heal", "rare")) == 6 and int(_db.adventure.curio_value("ap", "rarest")) == 1,
"恢复件 +6 当即回血(新入池种类,rare 档)· AP +1(rarest 档)")
"档位配额结构锚(四级 70/25/3/0 直映射承袭——迭代 20 T2):%s = %d 张" % [tier, int(_db.adventure.TIER_QUOTAS[tier])])
check(int(_db.adventure.deck_total()) == 98, "令牌池总量 = 98 张(四级 普通 70/优秀 25/稀有 3/传说 0——直映射承袭零偏离)")
check(int(_db.adventure.curio_value("gp", "common")) == 20 and int(_db.adventure.curio_value("gp", "excellent")) == 50
and int(_db.adventure.curio_value("attack", "common")) == 1 and int(_db.adventure.curio_value("attack", "excellent")) == 2
and int(_db.adventure.curio_value("max_hp", "common")) == 5 and int(_db.adventure.curio_value("max_hp", "excellent")) == 10
and int(_db.adventure.curio_value("armor", "common")) == 1 and int(_db.adventure.curio_value("armor", "excellent")) == 2,
"数值对(四级换代承袭):小GP 20/大GP 50 · 小增伤 +1/大 +2 · 小生命 +5/大 +10 · 小护甲 +1/大 +2")
check(int(_db.adventure.curio_value("heal", "excellent")) == 6 and int(_db.adventure.curio_value("ap", "rare")) == 1,
"恢复件 +6 当即回血(优秀档承袭)· AP +1(稀有档承袭)〔专长批 V14 换代〕")
check(int(_db.adventure.curio_cap("gp")) == 99 and int(_db.adventure.curio_cap("attack")) == 99,
"cap 占位在域(案②提前退役——99=实质无上限,实数归调参批)〔专长批 V8 形态面〕")
check(_db.attunement_growth != null and int(_db.attunement_slot_cap()) == 3
and Attunement.slots(_db, null) == 0,
"同调位读数源=attunement_growth 谓词表(slot_cap 3;未注入档求值 0——transitional_sync_slots 过渡键已退役,迭代 11 第①批 T7)")
@@ -427,8 +429,8 @@ func _smoke_adventure() -> void:
var k := 5.0 # hp+400 ⇒ 调试浮窗百分比后乘 ×5(加算先加、百分比后乘——生效次序口径)
var exp_base := maxi(1, int(round(float(int(_db.hero.max_hp)) * k)))
# 模拟档 v3.4 商店贪心购血(数值修复批)合法抬升——上限窗口 = 基础 + 加算区 3 件 + 购血余量;
# TP0 数值对后 max_hp 件有大生命 +10(rare 档)——上界按大件最坏构成 3×10+购血 15=+45(TP0 放宽)
var hp_ceiling := maxi(1, int(round(float(int(_db.hero.max_hp) + 3 * int(_db.adventure.curio_value("max_hp", "rare")) + 15) * k)))
# 大生命 +10(迭代 20 T2 四级换代:优秀档)——上界按大件最坏构成 3×10+购血 15=+45(TP0 放宽承袭)
var hp_ceiling := maxi(1, int(round(float(int(_db.hero.max_hp) + 3 * int(_db.adventure.curio_value("max_hp", "excellent")) + 15) * k)))
var seq_ok := seq.size() > 0 and int(seq[0]) == exp_base
for v in (seq as Array):
if int(v) < exp_base or int(v) > hp_ceiling:
@@ -640,14 +642,14 @@ func _smoke_feats() -> void:
var a_r0 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(71))
check(a_r0.start_adventure(71, {"first_script": true}), "规则改写型特性带场景:冒险启动(seed 71)")
var feat_tokens := 0
var rarest_tokens := 0
var rare_tier_tokens := 0
for t in a_r0._curio_deck:
if String((t as Dictionary).get("kind", "")) == "relic":
feat_tokens += 1
if String((t as Dictionary).get("tier", "")) == "rarest":
rarest_tokens += 1
check(feat_tokens == 27 and rarest_tokens == 6 and a_r0._curio_deck.size() == 125,
"规则改写型特性带入池:27 件(rare 档 21 + rarest 锚点 6)——牌库 98+27=125")
if String((t as Dictionary).get("tier", "")) == "rare":
rare_tier_tokens += 1
check(feat_tokens == 27 and rare_tier_tokens == 20 and a_r0._curio_deck.size() == 125,
"规则改写型特性带入池:27 件(transitional 直映射——旧 rare 名直通 14+旧 rarest 回退 6=稀有档 20、旧 common 7=普通档)——牌库 98+27=125〔专长批 V14 换代〕")
check(_db.feats.validate().is_empty(), "feat_table.validate 零违例(有行流派扫雷端铁律——magic 魔能共鸣 dig_reveal 订阅在案)")
# ② 档位激活引擎(纯函数直测——构造表 4 件 magic + 1 件 flag;内容数据驱动扩展批 T3 断言面随迁:
# 行=triggers 事件订阅形态,挂点投影断言换代=效果引擎订阅装载序〔feats 表序〕)
@@ -682,7 +684,7 @@ func _smoke_feats() -> void:
if String((t as Dictionary).get("kind", "")) == "relic":
deck_relic += 1
check(deck_relic == 5 and a_r._curio_deck.size() == 103,
"规则改写型特性带入池:5 行 relic 每件 1 张(common/rare→稀有档 rarest→罕见档)——牌库 98+5=103")
"规则改写型特性带入池:5 行 relic 每件 1 张(transitional——旧 common/rare→优秀档)——牌库 98+5=103")
# T4 渠道白名单断言(迭代 15 卡②——渠道轴定位:通关渠道只出专长/节点渠道零专长)
var feat_seen: Dictionary = {}
var node_relic_seen := false