主卡T5(拆件批wr7): 转发属性25条撤除+测量面改址收口——adv 4条(_curio_taken/_curio_deck/_feat_ticket_pity/_feat_ticket_sold直指件成员改写后删)、level 7条白盒属性删(内部直指_shop)、board 13条删(内部消费约30处改直引_palette/_hero_sprite件成员);A类直读47处+ui_input_probe 6处改指件;C类方法面调用全仓改adventure.stop().X(委托壳退役——契约5纯转传清偿,adv删pick_curio/apply_node_curio/skip_empty/refresh族/pool_stock/凭证委托11个,ctx组包改直引_curio.deck/feat_ticket_consider/cap_ok);新件压默认阈值(hero_ledger删_gain_seq序派生15变量合规;curio_stop删_attunement改_refresh_x_cap预算注入——装配集冒险期间锁死契约8等价,start/resume双路注入);battle_orchestrator压行还债(begin_battle局部变量归位);验证集清单重生成(66源文件/1596调用点,标签cond计数三对齐零差异)。S13读数:三宿主全部改善——adventure_runner类变量42→23(-19)/公开方法23→≤20归零、level_runner 38→28(-10,达标约30)/54→50、board_view 45→32(-13,精确达标);存量红面=新件5条NEW(接口块公开面29/31方法+迁移函数既有超标形态,原基线adventure_runner同函数同值登记)+恶化4条(battle拆件接线3条+level_map_screen 1条iter38存量漏登记——本批零触碰),收口前呈报用户裁决〔拆件批 V7〕
This commit is contained in:
1 parent
fa1409f491
commit
659d59edd3
19 files changed
+431
-552
No files matched your search
@@ -183,7 +183,7 @@ func _smoke_adventure() -> void:
|
||||
rw_pc = (rw.get("cands", []) as Array)[0] as Dictionary
|
||||
var rw_pick_ok := false
|
||||
if not rw_pc.is_empty() and rw.get("adr") != null:
|
||||
rw_pick_ok = rw["adr"].apply_node_curio(String(rw_pc.get("kind", "")), String(rw_pc.get("tier", "")), String(rw_pc.get("feat_id", "")))
|
||||
rw_pick_ok = (rw["adr"] as AdventureRunner).stop().apply_node_curio(String(rw_pc.get("kind", "")), String(rw_pc.get("tier", "")), String(rw_pc.get("feat_id", "")))
|
||||
Kit.check("奖励三选一点选兑付受理(件=%s)" % String(rw_pc.get("kind", "")), rw_pick_ok)
|
||||
var enc_run: Dictionary = _drive_to_pref(autoplay, "battle")
|
||||
var enc_probe: Dictionary = enc_run.get("enc", {}) as Dictionary
|
||||
@@ -361,7 +361,7 @@ func _smoke_adventure() -> void:
|
||||
Kit.check("未兑付推进拒绝(选择停点零自动推进契约)", not a8.continue_to_next_level())
|
||||
var l2_cands: Array = a8.stop()._pending["candidates"]
|
||||
var l2_pick: Dictionary = l2_cands[0]
|
||||
Kit.check("三选一点选兑付受理(候选取首件)", a8.pick_curio(String(l2_pick.get("kind", "")), String(l2_pick.get("tier", "")), String(l2_pick.get("feat_id", ""))))
|
||||
Kit.check("三选一点选兑付受理(候选取首件)", a8.stop().pick_curio(String(l2_pick.get("kind", "")), String(l2_pick.get("tier", "")), String(l2_pick.get("feat_id", ""))))
|
||||
var picked2: String = String(a8.stop()._resolved.get("picked", ""))
|
||||
var expect_acc: int = acc_shop + (int(a8.stop()._resolved.get("value", 0)) if picked2 == "max_hp" else 0)
|
||||
Kit.check("三选一属性件与商店购买同账累加(max_hp=%d = %d + 三选一%s)" % [a8.hero().bonus_total("max_hp"), acc_shop, picked2], a8.hero().bonus_total("max_hp") == expect_acc)
|
||||
@@ -392,10 +392,10 @@ func _smoke_adventure() -> void:
|
||||
# 无种类次数上限,「达上限剔除」语义由牌库耗尽承载)
|
||||
var a11 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(11))
|
||||
Kit.check("剔牌库/替换场景:冒险启动(seed 11——道具解锁集只含 wide_scout_band)", a11.start_adventure(11, {"treasure_unlocked": {"wide_scout_band": true}}))
|
||||
for di in range(a11._curio_deck.size() - 1, -1, -1):
|
||||
var dk := String((a11._curio_deck[di] as Dictionary).get("kind", ""))
|
||||
for di in range(a11._curio.deck.size() - 1, -1, -1):
|
||||
var dk := String((a11._curio.deck[di] as Dictionary).get("kind", ""))
|
||||
if dk == "attack" or dk == "ap":
|
||||
a11._curio_deck.remove_at(di)
|
||||
a11._curio.deck.remove_at(di)
|
||||
var draw: Array = a11.stop().draw_candidates()
|
||||
var draw_kinds := {}
|
||||
for t in draw:
|
||||
@@ -423,10 +423,10 @@ func _smoke_adventure() -> void:
|
||||
# ⑬ 奖励节点共享池(同库同池同摘牌;TP0:attack 令牌耗尽后节点域同样零出现)
|
||||
var a13 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(13))
|
||||
Kit.check("节点共享池场景:冒险启动(seed 13)", a13.start_adventure(13, {"treasure_unlocked": {"wide_scout_band": true}}))
|
||||
for di13 in range(a13._curio_deck.size() - 1, -1, -1):
|
||||
if String((a13._curio_deck[di13] as Dictionary).get("kind", "")) == "attack":
|
||||
a13._curio_deck.remove_at(di13)
|
||||
var ndraw: Dictionary = a13.node_curio_candidates()
|
||||
for di13 in range(a13._curio.deck.size() - 1, -1, -1):
|
||||
if String((a13._curio.deck[di13] as Dictionary).get("kind", "")) == "attack":
|
||||
a13._curio.deck.remove_at(di13)
|
||||
var ndraw: Dictionary = a13.stop().node_curio_candidates()
|
||||
var ncands13: Array = ndraw.get("candidates", []) as Array
|
||||
var has_attack13 := false
|
||||
for t in ncands13:
|
||||
@@ -434,10 +434,10 @@ func _smoke_adventure() -> void:
|
||||
has_attack13 = true
|
||||
break
|
||||
Kit.check("奖励节点共享池:令牌耗尽同样不出候选(同库同池——%s)" % str(ncands13), not has_attack13)
|
||||
a13.present_node_curio(ncands13)
|
||||
a13.present_node_curio([{"kind": "gp", "tier": "common"}])
|
||||
a13.stop().present_node_curio(ncands13)
|
||||
a13.stop().present_node_curio([{"kind": "gp", "tier": "common"}])
|
||||
var gp13: int = a13.hero().gp
|
||||
Kit.check("奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" % int(_db.adventure.curio_value("gp", "common")), a13.apply_node_curio("gp", "common") and a13.hero().gp == gp13 + int(_db.adventure.curio_value("gp", "common")))
|
||||
Kit.check("奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" % int(_db.adventure.curio_value("gp", "common")), a13.stop().apply_node_curio("gp", "common") and a13.hero().gp == gp13 + int(_db.adventure.curio_value("gp", "common")))
|
||||
Kit.check("节点停点态兑付后清零(恰一次语义同构)", a13.stop()._node_pending.is_empty())
|
||||
var s10: Dictionary = a10.summary
|
||||
Kit.check("放弃摘要:abandoned · 未打穿(已获大奖励不追回——同失败型结算)", String(s10.get("result", "")) == "abandoned" and not bool(s10.get("cleared", true)))
|
||||
@@ -457,18 +457,18 @@ func _smoke_feats() -> void:
|
||||
Kit.check("专长带场景:冒险启动(seed 71)", a_r0.start_adventure(71))
|
||||
var feat_tokens := 0
|
||||
var tier_counts := {}
|
||||
for t in a_r0._curio_deck:
|
||||
for t in a_r0._curio.deck:
|
||||
if String((t as Dictionary).get("kind", "")) == "relic":
|
||||
feat_tokens += 1
|
||||
var tk := String((t as Dictionary).get("tier", ""))
|
||||
tier_counts[tk] = int(tier_counts.get(tk, 0)) + 1
|
||||
Kit.check("专长带入池:30 件四级直映射(普通 12/优秀 9/稀有 9/传说 0)——牌库 102+30=132〔专长批 V2+卡② 完美保险迁入〕", feat_tokens == 30 and int(tier_counts.get("common", 0)) == 12 and int(tier_counts.get("excellent", 0)) == 9 and int(tier_counts.get("rare", 0)) == 9 and a_r0._curio_deck.size() == 132)
|
||||
Kit.check("专长带入池:30 件四级直映射(普通 12/优秀 9/稀有 9/传说 0)——牌库 102+30=132〔专长批 V2+卡② 完美保险迁入〕", feat_tokens == 30 and int(tier_counts.get("common", 0)) == 12 and int(tier_counts.get("excellent", 0)) == 9 and int(tier_counts.get("rare", 0)) == 9 and a_r0._curio.deck.size() == 132)
|
||||
# ② 旧 27 件零残留钉面(V2——arcane_ember 系旧件表首行;全仓 grep 零残留归静态核查)
|
||||
Kit.check("旧 27 件已退役:arcane_ember/magma_body 表内零残留〔专长批 V2〕", _db.feats.row_by_id("arcane_ember").is_empty() and _db.feats.row_by_id("magma_body").is_empty())
|
||||
Kit.check("迁出收尾:treasure_items 无 venom_edge/seal_burst 行(同调目录自然收窄)〔专长批 V13〕", _db.treasure_items.row_by_id("venom_edge").is_empty() and _db.treasure_items.row_by_id("seal_burst").is_empty())
|
||||
# ③ 契约面静态钉扎(V18/V19/V21/V22——人工核对 V20/V21 裁决面以外的可机检半)
|
||||
var kinds_ok := true
|
||||
for t in a_r0._curio_deck:
|
||||
for t in a_r0._curio.deck:
|
||||
var kk := String((t as Dictionary).get("kind", ""))
|
||||
if kk != "relic" and not _db.adventure.CURIO_KINDS.has(kk):
|
||||
kinds_ok = false
|
||||
@@ -510,10 +510,10 @@ func _smoke_feats() -> void:
|
||||
var a_r = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(72))
|
||||
Kit.check("专长带场景:冒险启动(seed 72——注入 5 行临时表)", a_r.start_adventure(72))
|
||||
var deck_relic := 0
|
||||
for t in a_r._curio_deck:
|
||||
for t in a_r._curio.deck:
|
||||
if String((t as Dictionary).get("kind", "")) == "relic":
|
||||
deck_relic += 1
|
||||
Kit.check("专长带入池:5 行 relic 每件 1 张(四级 rarity 直映射)——牌库 102+5=107", deck_relic == 5 and a_r._curio_deck.size() == 107)
|
||||
Kit.check("专长带入池:5 行 relic 每件 1 张(四级 rarity 直映射)——牌库 102+5=107", deck_relic == 5 and a_r._curio.deck.size() == 107)
|
||||
# 渠道白名单断言(渠道轴定位:关卡完成渠道只出专长/节点渠道零专长)
|
||||
var feat_seen: Dictionary = {}
|
||||
var node_relic_seen := false
|
||||
@@ -531,19 +531,19 @@ func _smoke_feats() -> void:
|
||||
a_t.start_adventure(91)
|
||||
var stock_before := {}
|
||||
for kk in ["attack", "gp", "heal"]:
|
||||
stock_before[kk] = a_t.pool_stock(kk)
|
||||
stock_before[kk] = a_t.stop().pool_stock(kk)
|
||||
a_t.stop()._node_pending = {"candidates": [{"kind": "feat_ticket", "tier": "excellent"}, {"kind": "attack", "tier": "common"}]}
|
||||
Kit.check("A5 专长凭证兑付受理(节点渠道——拿到即开)", a_t.apply_node_curio("feat_ticket", "excellent"))
|
||||
var tkt_cands: Array = (a_t.node_curio_pending_state().get("candidates", []) as Array)
|
||||
Kit.check("A5 专长凭证兑付受理(节点渠道——拿到即开)", a_t.stop().apply_node_curio("feat_ticket", "excellent"))
|
||||
var tkt_cands: Array = (a_t.stop().node_curio_pending_state().get("candidates", []) as Array)
|
||||
var tkt_all_relic := tkt_cands.size() > 0
|
||||
for t in tkt_cands:
|
||||
if String((t as Dictionary).get("kind", "")) != "relic":
|
||||
tkt_all_relic = false
|
||||
Kit.check("A5 拿到即开——停点候选已替换为专长三选一(全 relic)", tkt_all_relic)
|
||||
Kit.check("A5 零摘牌——专长凭证兑付不动令牌库(不进持有集)", a_t.pool_stock("attack") == int(stock_before["attack"]) and a_t.pool_stock("gp") == int(stock_before["gp"]))
|
||||
Kit.check("A5 零摘牌——专长凭证兑付不动令牌库(不进持有集)", a_t.stop().pool_stock("attack") == int(stock_before["attack"]) and a_t.stop().pool_stock("gp") == int(stock_before["gp"]))
|
||||
Kit.check("A5 无专长凭证残留持有集", not (a_t.feats_held() as Array).has("feat_ticket"))
|
||||
var feats_n := (a_t.feats_held() as Array).size()
|
||||
a_t.apply_node_curio("relic", String((tkt_cands[0] as Dictionary).get("tier", "rare")), String((tkt_cands[0] as Dictionary).get("feat_id", "")))
|
||||
a_t.stop().apply_node_curio("relic", String((tkt_cands[0] as Dictionary).get("tier", "rare")), String((tkt_cands[0] as Dictionary).get("feat_id", "")))
|
||||
Kit.check("A5 专长面兑付受理(专长凭证开出候选可正常入持有集)", (a_t.feats_held() as Array).size() == feats_n + 1)
|
||||
# A6 保底:pity 直填 5 → 下次展示必出(第 6 次必出口径);限购满 → 恒不触发
|
||||
a_t.stop()._deck.ticket_sold = 0 # A5 已兑付一枚专长凭证(sold=1=limit)——A6 段重置计数隔离验证
|
||||
@@ -563,7 +563,7 @@ func _smoke_feats() -> void:
|
||||
break
|
||||
Kit.check("A6 概率面存在(chance=20% 200 展示内必出现——零触发=概率面失守)", offered)
|
||||
a_r.stop()._pending = {"candidates": [{"kind": "relic", "tier": "rare", "feat_id": "x3"}, {"kind": "gp", "tier": "common"}], "payload": {}}
|
||||
Kit.check("relic 兑付:入持有集 + 牌库摘牌(选中踢池——池库存 %d→%d)" % [deck_relic, deck_relic - 1], a_r.pick_curio("relic", "rare", "x3") and (a_r.feats_held() as Array).has("x3") and a_r.pool_stock("relic") == deck_relic - 1)
|
||||
Kit.check("relic 兑付:入持有集 + 牌库摘牌(选中踢池——池库存 %d→%d)" % [deck_relic, deck_relic - 1], a_r.stop().pick_curio("relic", "rare", "x3") and (a_r.feats_held() as Array).has("x3") and a_r.stop().pool_stock("relic") == deck_relic - 1)
|
||||
# 断点往返三条(基点 1420–1426:relics 快照/计数器键/余库逐枚还原)按主会话裁决②改判集成宿主——
|
||||
# 驱动代码(save_manager 装配+_on_level_finished+快照取读)随三条同去,集成批落位时重建。
|
||||
_db.feats = live_rows # 还原现行表(共享 _db 防污染——后续冒烟段零感知)
|
||||
@@ -782,7 +782,7 @@ func _adv_drive_to_shop(a, st: Dictionary, autoplay) -> bool:
|
||||
if not a.stop()._pending.is_empty():
|
||||
var bcands: Array = a.stop()._pending["candidates"]
|
||||
var bpick: Dictionary = autoplay._pick_token(bcands)
|
||||
a.pick_curio(String(bpick.get("kind", "")), String(bpick.get("tier", "")), String(bpick.get("feat_id", "")))
|
||||
a.stop().pick_curio(String(bpick.get("kind", "")), String(bpick.get("tier", "")), String(bpick.get("feat_id", "")))
|
||||
a.continue_to_next_level()
|
||||
continue
|
||||
var r = a.runner()
|
||||
@@ -796,12 +796,12 @@ func _adv_drive_to_shop(a, st: Dictionary, autoplay) -> bool:
|
||||
var t := String(r.current_node().get("type", ""))
|
||||
if t == "reward":
|
||||
# 奖励节点三选一(确定性选件、替换放弃新件、兑付确认回图;TP0 令牌化)
|
||||
var ndraw: Dictionary = a.node_curio_candidates()
|
||||
var ndraw: Dictionary = a.stop().node_curio_candidates()
|
||||
var ncands: Array = ndraw.get("candidates", []) as Array
|
||||
if not ncands.is_empty():
|
||||
a.present_node_curio(ncands)
|
||||
a.stop().present_node_curio(ncands)
|
||||
var npick: Dictionary = autoplay._pick_token(ncands)
|
||||
a.apply_node_curio(String(npick.get("kind", "")), String(npick.get("tier", "")), String(npick.get("feat_id", "")))
|
||||
a.stop().apply_node_curio(String(npick.get("kind", "")), String(npick.get("tier", "")), String(npick.get("feat_id", "")))
|
||||
r.continue_after_node()
|
||||
elif t == "rest":
|
||||
r.continue_after_node()
|
||||
@@ -841,8 +841,8 @@ func _drive_to_pref(autoplay, prefer: String) -> Dictionary:
|
||||
if prefer == "battle":
|
||||
out["enc"] = r.current_battle().encounter
|
||||
else:
|
||||
var cands: Array = (adr.node_curio_candidates() as Dictionary).get("candidates", []) as Array
|
||||
adr.present_node_curio(cands)
|
||||
var cands: Array = (adr.stop().node_curio_candidates() as Dictionary).get("candidates", []) as Array
|
||||
adr.stop().present_node_curio(cands)
|
||||
out["cands"] = cands
|
||||
out["pending"] = not (adr.stop()._node_pending as Dictionary).is_empty()
|
||||
return out
|
||||
|
||||
@@ -93,7 +93,7 @@ func _init() -> void:
|
||||
adr_e.set_save_manager(sm_e)
|
||||
var params_e := {"hero_override": {}, "treasure_unlocked": {"wide_scout_band": true}}
|
||||
Kit.check_quiet(adr_e.start_adventure(4321, params_e), "P5 冒险启动(seed 4321)")
|
||||
adr_e._curio_taken["attack"] = 1 # 白盒预置计数(断点附随件往返的判据面——计数不可由加算区反推)
|
||||
adr_e._curio.taken["attack"] = 1 # 白盒预置计数(断点附随件往返的判据面——计数不可由加算区反推)
|
||||
adr_e._on_level_finished({"result": "victory", "hp": 30, "node_index": 1, "node_id": 1, "node_type": "shop"})
|
||||
var cands_e: Array = (adr_e.stop()._pending.get("candidates", []) as Array).duplicate()
|
||||
Kit.check_quiet(not cands_e.is_empty(), "P5 非末关的关卡完成三选一停点在案(直调 victory——L1 非末关)")
|
||||
@@ -110,13 +110,13 @@ func _init() -> void:
|
||||
Kit.check_quiet(adr_f.resume_adventure(bp_f, params_e), "P5 续玩受理(选择态分支)")
|
||||
Kit.check_quiet(adr_f.runner() == null, "P5 续玩不重跑关卡(三选一停点直回,_start_current_level 未走)")
|
||||
Kit.check_quiet(got_cands["cands"] == cands_e, "P5 续玩候选不重抽(逐位一致)")
|
||||
Kit.check_quiet(int(adr_f._curio_taken["attack"]) == 1, "P5 次数计数恢复一致(牌库剔除态续接)")
|
||||
Kit.check_quiet(int(adr_f._curio.taken["attack"]) == 1, "P5 次数计数恢复一致(牌库剔除态续接)")
|
||||
Kit.check_quiet(not adr_f.continue_to_next_level(), "P5 未兑付推进拒绝(续玩态零自动推进同契约)")
|
||||
var pick_e: Dictionary = cands_e[0]
|
||||
Kit.check_quiet(adr_f.pick_curio(String(pick_e.get("kind", "")), String(pick_e.get("tier", "")), String(pick_e.get("feat_id", ""))), "P5 点选兑付受理")
|
||||
Kit.check_quiet(adr_f.stop().pick_curio(String(pick_e.get("kind", "")), String(pick_e.get("tier", "")), String(pick_e.get("feat_id", ""))), "P5 点选兑付受理")
|
||||
var picked_e: String = String(adr_f.stop()._resolved.get("picked", ""))
|
||||
if adr_f._curio_taken.has(picked_e):
|
||||
Kit.check_quiet(int(adr_f._curio_taken[picked_e]) == (2 if picked_e == "attack" else 1),
|
||||
if adr_f._curio.taken.has(picked_e):
|
||||
Kit.check_quiet(int(adr_f._curio.taken[picked_e]) == (2 if picked_e == "attack" else 1),
|
||||
"P5 兑付计数一致(%s——预置 1 + 本次兑付)" % picked_e)
|
||||
Kit.check_quiet(sm_f.has_breakpoint(), "P5 兑付后停点快照在档(已兑付待推进态可中断)")
|
||||
var bp_g: Dictionary = sm_f.breakpoint_snapshot()
|
||||
|
||||
@@ -20,30 +20,30 @@ func _init() -> void:
|
||||
# ---- ① 停点在途谓词:无停点时免费/付费刷新皆拒绝(付费路径扣费前置校验防空转烧钱包)----
|
||||
var adr = load("res://core/adventure_runner.gd").new(db, load("res://core/rng_service.gd").new())
|
||||
Kit.check_quiet(adr.start_adventure(1234, {"hero_override": {}, "treasure_unlocked": {}}), "冒险启动(种子 1234——刷新重抽需真实令牌池)")
|
||||
Kit.check_quiet(adr.curio_stop_pending() == false, "无停点=在途谓词 false")
|
||||
Kit.check_quiet(adr.refresh_curio() == false and adr.refresh_curio_paid() == false, "无停点:免费/付费刷新皆拒绝零副作用")
|
||||
Kit.check_quiet(adr.stop().curio_stop_pending() == false, "无停点=在途谓词 false")
|
||||
Kit.check_quiet(adr.stop().refresh_curio() == false and adr.stop().refresh_curio_paid() == false, "无停点:免费/付费刷新皆拒绝零副作用")
|
||||
|
||||
# ---- ② 免费位优先序 X→Y(白盒造关卡完成停点——smoke_all ⑫ 同构)----
|
||||
adr.stop()._pending = {"candidates": _cands(), "payload": {}}
|
||||
Kit.check_quiet(adr.curio_stop_pending() == true, "关卡完成停点在途=谓词 true")
|
||||
Kit.check_quiet(adr.stop().curio_stop_pending() == true, "关卡完成停点在途=谓词 true")
|
||||
adr.stop()._refresh_x = 1
|
||||
adr.stop()._refresh_y = 2
|
||||
Kit.check_quiet(adr.refresh_curio() and adr.stop()._refresh_x == 0 and adr.stop()._refresh_y == 2, "X 优先消耗(x1y2→x0y2)")
|
||||
Kit.check_quiet(adr.refresh_curio() and adr.stop()._refresh_y == 1, "X 穷转 Y 池(y2→y1)")
|
||||
Kit.check_quiet(adr.stop().refresh_curio() and adr.stop()._refresh_x == 0 and adr.stop()._refresh_y == 2, "X 优先消耗(x1y2→x0y2)")
|
||||
Kit.check_quiet(adr.stop().refresh_curio() and adr.stop()._refresh_y == 1, "X 穷转 Y 池(y2→y1)")
|
||||
|
||||
# ---- ③ GP 付费档:计数递增爬价 + 零触碰免费位 ----
|
||||
Kit.check_quiet(adr.curio_refresh_gp_cost() == base, "首刷报价=基价(免费位尚余 y1,报价独立于免费位)")
|
||||
Kit.check_quiet(adr.refresh_curio_paid() and adr.stop()._refresh_y == 1, "付费刷新不触碰免费位(y1 保持)")
|
||||
Kit.check_quiet(adr.curio_refresh_gp_cost() == int(ceil(float(base) * curve)), "二刷价爬升=ceil(基价×曲线)(已付费刷=1)")
|
||||
Kit.check_quiet(adr.refresh_curio_paid() and adr.curio_refresh_gp_cost() == int(ceil(float(base) * curve * curve)), "三刷价再爬升=ceil(基价×曲线²)(已付费刷=2)")
|
||||
Kit.check_quiet(adr.stop().curio_refresh_gp_cost() == base, "首刷报价=基价(免费位尚余 y1,报价独立于免费位)")
|
||||
Kit.check_quiet(adr.stop().refresh_curio_paid() and adr.stop()._refresh_y == 1, "付费刷新不触碰免费位(y1 保持)")
|
||||
Kit.check_quiet(adr.stop().curio_refresh_gp_cost() == int(ceil(float(base) * curve)), "二刷价爬升=ceil(基价×曲线)(已付费刷=1)")
|
||||
Kit.check_quiet(adr.stop().refresh_curio_paid() and adr.stop().curio_refresh_gp_cost() == int(ceil(float(base) * curve * curve)), "三刷价再爬升=ceil(基价×曲线²)(已付费刷=2)")
|
||||
|
||||
# ---- ④ 停点重建清零付费计数(对齐商店进店清零——不结转)----
|
||||
adr.present_node_curio(_cands())
|
||||
Kit.check_quiet(adr.stop()._paid_refreshes == 0 and adr.curio_refresh_gp_cost() == base, "节点停点重建=付费计数清零回基价")
|
||||
adr.refresh_curio_paid()
|
||||
adr.stop().present_node_curio(_cands())
|
||||
Kit.check_quiet(adr.stop()._paid_refreshes == 0 and adr.stop().curio_refresh_gp_cost() == base, "节点停点重建=付费计数清零回基价")
|
||||
adr.stop().refresh_curio_paid()
|
||||
Kit.check_quiet(adr.stop()._paid_refreshes == 1, "付费刷新计数在途递增(=1)")
|
||||
adr.present_node_curio(_cands())
|
||||
Kit.check_quiet(adr.curio_refresh_gp_cost() == base, "再碰三选一付费计数仍清零(同 X 余量不结转口径)")
|
||||
adr.stop().present_node_curio(_cands())
|
||||
Kit.check_quiet(adr.stop().curio_refresh_gp_cost() == base, "再碰三选一付费计数仍清零(同 X 余量不结转口径)")
|
||||
|
||||
# ---- ⑤ 钱包单口支出 spend_gp(LevelRunner——三选一付费档与商店刷新共用同一冒险钱包)----
|
||||
var lr = load("res://core/level_runner.gd").new(db, load("res://core/rng_service.gd").new())
|
||||
|
||||
@@ -33,20 +33,20 @@ func _init() -> void:
|
||||
# V9-1 刷新券:入存量账(冒险级)——反例=写进 _attune_refresh_x(X 每停点重置会吞存量)
|
||||
a.stop()._reset_refresh_x() # X 归零基线(模拟新停点)
|
||||
Kit.check_quiet(a.stop()._apply_curio_pick("refresh", "excellent", 1), "刷新券兑付受理〔专长批 V9〕")
|
||||
Kit.check_quiet(a.refresh_stock() == 1 and a.stop()._refresh_x == 0,
|
||||
Kit.check_quiet(a.stop().refresh_stock() == 1 and a.stop()._refresh_x == 0,
|
||||
"F-1 修复:刷新券入存量账、X 账零写入(写错账反例不复发)〔专长批 V9〕")
|
||||
a.stop()._reset_refresh_x() # 再碰停点——X 重置但存量不吞
|
||||
Kit.check_quiet(a.refresh_stock() == 1 and a.attune_refresh_left() == 1,
|
||||
Kit.check_quiet(a.stop().refresh_stock() == 1 and a.stop().attune_refresh_left() == 1,
|
||||
"F-1 修复:停点重置后存量账存活(attune_refresh_left 含第三源)〔专长批 V9〕")
|
||||
# 消耗序:X 优先 → 存量(无 X 无 Y 时吃存量;refresh_curio 前置=在途停点)
|
||||
a.stop()._refresh_stock = 1
|
||||
a.stop()._refresh_y = 0
|
||||
a.stop()._node_pending = {"candidates": [{"kind": "attack", "tier": "common"}]}
|
||||
Kit.check_quiet(a.refresh_curio() and a.refresh_stock() == 0,
|
||||
Kit.check_quiet(a.stop().refresh_curio() and a.stop().refresh_stock() == 0,
|
||||
"刷新消耗序:X/Y 空时吃存量账〔专长批 V9〕")
|
||||
a.stop()._node_pending = {}
|
||||
# 摘牌:选中即消尽(禁早退路径零摘牌)
|
||||
var deck_refresh_before: int = a.pool_stock("refresh")
|
||||
var deck_refresh_before: int = a.stop().pool_stock("refresh")
|
||||
Kit.check_quiet(deck_refresh_before == 0 or true, "牌库 refresh 令牌读数在域(投放 %d)" % deck_refresh_before)
|
||||
|
||||
# V9-2 储备金袋:待注入账 + 战首注入(节点级)
|
||||
@@ -89,26 +89,26 @@ func _init() -> void:
|
||||
Kit.check_quiet(db.adventure.validate().is_empty(), "AdventureTable.validate() 零违例(两件出池后)〔卡② R3〕")
|
||||
|
||||
# V9-6 全链:凭证令牌兑付=牌库摘牌(选中即消尽)〔拆件批 V2——cs3 凭证拿到即开现役断言承继〕
|
||||
a._curio_deck = [{"kind": "rap", "tier": "rare"}, {"kind": "attack", "tier": "common"}]
|
||||
a.stop()._pending = {"candidates": a._curio_deck.duplicate()}
|
||||
Kit.check_quiet(a.pick_curio("rap", "rare") and a.pool_stock("rap") == 0,
|
||||
a._curio.deck = [{"kind": "rap", "tier": "rare"}, {"kind": "attack", "tier": "common"}]
|
||||
a.stop()._pending = {"candidates": a._curio.deck.duplicate()}
|
||||
Kit.check_quiet(a.stop().pick_curio("rap", "rare") and a.stop().pool_stock("rap") == 0,
|
||||
"凭证令牌:pick_curio 摘牌(选中踢池——与属性件同语义)〔专长批 V9〕")
|
||||
|
||||
# V10-1 留任 2 件路由与值不变:gp 钱包/heal 当即回血(每次点选独立停点态)
|
||||
a._curio_deck = [{"kind": "gp", "tier": "common"}, {"kind": "heal", "tier": "excellent"}]
|
||||
a._curio.deck = [{"kind": "gp", "tier": "common"}, {"kind": "heal", "tier": "excellent"}]
|
||||
a.stop()._pending = {"candidates": [{"kind": "gp", "tier": "common"}]}
|
||||
var gp_taken_before := int(a._curio_taken.get("gp", 0))
|
||||
Kit.check_quiet(a.pick_curio("gp", "common") and int(a._curio_taken.get("gp", 0)) == gp_taken_before + 1,
|
||||
var gp_taken_before := int(a._curio.taken.get("gp", 0))
|
||||
Kit.check_quiet(a.stop().pick_curio("gp", "common") and int(a._curio.taken.get("gp", 0)) == gp_taken_before + 1,
|
||||
"留任小GP 袋:GP 通道兑付受理(gp 计数入账——路由零变化)〔专长批 V10〕")
|
||||
var hp_before: int = a.hero().hero_hp
|
||||
a.stop()._pending = {"candidates": [{"kind": "heal", "tier": "excellent"}]}
|
||||
Kit.check_quiet(a.pick_curio("heal", "excellent") and a.hero().hero_hp == mini(hp_before + int(db.adventure.curio_value("heal", "excellent")), a.effective_max_hp()),
|
||||
Kit.check_quiet(a.stop().pick_curio("heal", "excellent") and a.hero().hero_hp == mini(hp_before + int(db.adventure.curio_value("heal", "excellent")), a.effective_max_hp()),
|
||||
"留任应急口粮:当即回血 +6 封顶生效上限〔专长批 V10〕")
|
||||
# V10-2 行动点上限归属性轴:ap kind 走加算区第四轴
|
||||
a._curio_deck = [{"kind": "ap", "tier": "rare"}]
|
||||
a.stop()._pending = {"candidates": a._curio_deck.duplicate()}
|
||||
a._curio.deck = [{"kind": "ap", "tier": "rare"}]
|
||||
a.stop()._pending = {"candidates": a._curio.deck.duplicate()}
|
||||
var ap_bonus_before: int = a.hero().bonus_total("ap")
|
||||
Kit.check_quiet(a.pick_curio("ap", "rare") and a.hero().bonus_total("ap") == ap_bonus_before + int(db.adventure.curio_value("ap", "rare")),
|
||||
Kit.check_quiet(a.stop().pick_curio("ap", "rare") and a.hero().bonus_total("ap") == ap_bonus_before + int(db.adventure.curio_value("ap", "rare")),
|
||||
"行动点上限归属性轴:ap 兑付写加算区第四轴(bonus.ap 承载)〔专长批 V10〕")
|
||||
|
||||
# V16——断点扩容往返:新账本随断点快照/续玩回填(breakpoint_resume_test P5 同构)
|
||||
@@ -138,7 +138,7 @@ func _init() -> void:
|
||||
var b4 = load("res://core/adventure_runner.gd").new(db, load("res://core/rng_service.gd").new())
|
||||
Kit.check_quiet(b4.resume_adventure(bp_legacy2, {}),
|
||||
"V13:旧档 adventure_counters 含改名前旧键续玩受理零崩溃(无迁移——旧键留桶成死键)〔卡② V13/H1〕")
|
||||
Kit.check_quiet(int(b2.adventure_counters.get("pain_layers", -1)) == 3 and b2.refresh_stock() == 2,
|
||||
Kit.check_quiet(int(b2.adventure_counters.get("pain_layers", -1)) == 3 and b2.stop().refresh_stock() == 2,
|
||||
"V16:续玩回填逐项一致(adventure 桶随断点往返·计数恢复)〔无状态化 V3〕")
|
||||
# V25 完美保险专长验收组(R2 全项:装载/限次一次/计数纯净/两账相减/跨战清零/事件不吞)
|
||||
var fi: Dictionary = db.feats.row_by_id("perfect_insurance")
|
||||
|
||||
@@ -1317,12 +1317,12 @@ func _smoke_shop_pool() -> void:
|
||||
var tier := String(buy_c.get("tier", ""))
|
||||
var val_map := {"attack": "atk", "max_hp": "max_hp", "armor": "armor_class", "ap": "ap"}
|
||||
var gp0: int = int(r8.gp)
|
||||
var taken0: int = int(a8._curio_taken.get(kind, 0))
|
||||
var taken0: int = int(a8._curio.taken.get(kind, 0))
|
||||
var val0: int = a8.hero().bonus_total(String(val_map[kind]))
|
||||
Kit.check("购买受理(pool 口——%s|%s)" % [kind, tier], r8.buy_pool_item(kind))
|
||||
Kit.check("钱包扣现价(%d → %d)" % [gp0, int(r8.gp)], int(r8.gp) == gp0 - int(buy_c.get("price", 0)))
|
||||
Kit.check("加算区 +令牌档位件值(池件=奖励件本体——%s|%s %+d)" % [kind, tier, int(_db.adventure.curio_value(kind, tier))], a8.hero().bonus_total(String(val_map[kind])) == val0 + int(_db.adventure.curio_value(kind, tier)))
|
||||
Kit.check("共享池账本 -1(跨渠道单点——taken %d → %d)" % [taken0, int(a8._curio_taken.get(kind, 0))], int(a8._curio_taken.get(kind, 0)) == taken0 + 1)
|
||||
Kit.check("共享池账本 -1(跨渠道单点——taken %d → %d)" % [taken0, int(a8._curio.taken.get(kind, 0))], int(a8._curio.taken.get(kind, 0)) == taken0 + 1)
|
||||
# A 链:同visit 第二购现价 = ceil(base×b^(l2−1)×A^1)(货架已全重抽——新卡新价同公式)
|
||||
# A 链:白盒抬 GP 保证第二购场景确定构造(直改测试基建——非生产行为)
|
||||
r8.gp = int(r8.gp) + 64
|
||||
@@ -1347,9 +1347,9 @@ func _smoke_shop_pool() -> void:
|
||||
cut_seen = true
|
||||
Kit.check("切边件零入店(40 次重抽零 gp/aux——负交易切边+三轴 doctrine)", not cut_seen)
|
||||
# ⑤ 池空硬闸(库存尽剔出牌库——TP0:white-box 耗尽 attack 令牌后货架零 attack + 消费口拒绝)
|
||||
for di8 in range(a8._curio_deck.size() - 1, -1, -1):
|
||||
if String((a8._curio_deck[di8] as Dictionary).get("kind", "")) == "attack":
|
||||
a8._curio_deck.remove_at(di8)
|
||||
for di8 in range(a8._curio.deck.size() - 1, -1, -1):
|
||||
if String((a8._curio.deck[di8] as Dictionary).get("kind", "")) == "attack":
|
||||
a8._curio.deck.remove_at(di8)
|
||||
var attack_seen := false
|
||||
for i in 40:
|
||||
r8._shop_draw_shelf()
|
||||
@@ -1357,10 +1357,10 @@ func _smoke_shop_pool() -> void:
|
||||
attack_seen = true
|
||||
break
|
||||
Kit.check("库存尽剔牌库(attack 令牌耗尽——池消耗即上限跨渠道共库 reward→shop 向)", not attack_seen)
|
||||
var stock_before: int = a8.pool_stock("attack")
|
||||
Kit.check("池空消费拒绝(handler 零副作用——买光即枯竭硬闸)", not a8.stop().consume_pool_purchase("attack", "common") and a8.pool_stock("attack") == stock_before)
|
||||
var stock_before: int = a8.stop().pool_stock("attack")
|
||||
Kit.check("池空消费拒绝(handler 零副作用——买光即枯竭硬闸)", not a8.stop().consume_pool_purchase("attack", "common") and a8.stop().pool_stock("attack") == stock_before)
|
||||
# ⑥ 跨渠道共库 shop→reward 向:回填一枚 attack 令牌 → 消费口受理 → 奖励牌库同步摘牌
|
||||
a8._curio_deck.append({"kind": "attack", "tier": "common"})
|
||||
a8._curio.deck.append({"kind": "attack", "tier": "common"})
|
||||
Kit.check("商店消费口受理(停点件兑付单点同口——真单点库)〔拆件批 V3〕", a8.stop().consume_pool_purchase("attack", "common"))
|
||||
var reward_attack_seen := false
|
||||
for t6 in a8.stop().draw_candidates():
|
||||
@@ -1407,7 +1407,7 @@ func _adv_drive_to_shop(a, st: Dictionary, autoplay) -> bool:
|
||||
if not a.stop()._pending.is_empty():
|
||||
var bcands: Array = a.stop()._pending["candidates"]
|
||||
var bpick: Dictionary = autoplay._pick_token(bcands)
|
||||
a.pick_curio(String(bpick.get("kind", "")), String(bpick.get("tier", "")), String(bpick.get("feat_id", "")))
|
||||
a.stop().pick_curio(String(bpick.get("kind", "")), String(bpick.get("tier", "")), String(bpick.get("feat_id", "")))
|
||||
a.continue_to_next_level()
|
||||
continue
|
||||
var r = a.runner()
|
||||
@@ -1421,12 +1421,12 @@ func _adv_drive_to_shop(a, st: Dictionary, autoplay) -> bool:
|
||||
var t := String(r.current_node().get("type", ""))
|
||||
if t == "reward":
|
||||
# 奖励节点三选一(确定性选件、替换放弃新件、兑付确认回图;TP0 令牌化)
|
||||
var ndraw: Dictionary = a.node_curio_candidates()
|
||||
var ndraw: Dictionary = a.stop().node_curio_candidates()
|
||||
var ncands: Array = ndraw.get("candidates", []) as Array
|
||||
if not ncands.is_empty():
|
||||
a.present_node_curio(ncands)
|
||||
a.stop().present_node_curio(ncands)
|
||||
var npick: Dictionary = autoplay._pick_token(ncands)
|
||||
a.apply_node_curio(String(npick.get("kind", "")), String(npick.get("tier", "")), String(npick.get("feat_id", "")))
|
||||
a.stop().apply_node_curio(String(npick.get("kind", "")), String(npick.get("tier", "")), String(npick.get("feat_id", "")))
|
||||
r.continue_after_node()
|
||||
elif t == "rest":
|
||||
r.continue_after_node()
|
||||
|
||||
@@ -294,13 +294,13 @@ func _meta_settle_and_workshop() -> void:
|
||||
a12.stop()._refresh_y = 2
|
||||
a12.stop()._pending = {"candidates": [{"kind": "gp", "tier": "common"}, {"kind": "attack", "tier": "common"}, {"kind": "max_hp", "tier": "common"}], "payload": {}}
|
||||
Kit.check("刷新双计数器——X 优先消耗(x1y2 → x0y2)",
|
||||
a12.refresh_curio() and a12.stop()._refresh_x == 0 and a12.stop()._refresh_y == 2)
|
||||
a12.stop().refresh_curio() and a12.stop()._refresh_x == 0 and a12.stop()._refresh_y == 2)
|
||||
Kit.check("刷新双计数器——X 耗尽转 Y 池、池竭拒绝(x0y2 → y0 → 第四次 false 零副作用)",
|
||||
a12.refresh_curio() and a12.refresh_curio() and a12.stop()._refresh_y == 0
|
||||
and a12.refresh_curio() == false)
|
||||
a12.stop().refresh_curio() and a12.stop().refresh_curio() and a12.stop()._refresh_y == 0
|
||||
and a12.stop().refresh_curio() == false)
|
||||
a12.stop()._reset_refresh_x()
|
||||
Kit.check("刷新 X 每碰三选一重置(不结转;新目录无 bonus_refresh 行源——X 机制保留恒 0 空转,存量加仓走 _refresh_stock=刷新练习 V8)〔秘宝批换代〕",
|
||||
a12.stop()._refresh_x == 0 and a12.attune_refresh_left() == 0)
|
||||
a12.stop()._refresh_x == 0 and a12.stop().attune_refresh_left() == 0)
|
||||
# ⑬ 主菜单开局传参面(开新/续玩两入口同调三键随开局下传防回归:真实入口曾
|
||||
# 三键恒空(缺陷①),冒烟夹具直呼 runner 参数面拦不住——此处直呼 main.build_adventure_params
|
||||
# 单测统一构造面(static 免实例化整菜单场景;真实两入口共用本构造),取值与营地投影同源)
|
||||
@@ -728,10 +728,11 @@ func _smoke_tree_rules() -> void:
|
||||
int(orch2.action_economy.pending_ap_delta()) == 0)
|
||||
# 树限次按关清零改由 LevelRunner.level_counters 随 new 承载(旧硬编码名单冒烟断言随函数删除——换代同生死;新语义由 V4/V5 段承载)
|
||||
# 财富之道·散:商品标价折价(level_runner 计价单点)
|
||||
var lr = load("res://core/level_runner.gd").new(_db, _fresh_rng(777004))
|
||||
lr.set_tree_rules([])
|
||||
var lr = load("res://core/level_runner.gd").new(_db, _fresh_rng(777004),
|
||||
{"tree_rules": []}) # 构造注入(拆件批 T3——setter 群退役)
|
||||
Kit.check("散未激活:商品标价原价(无 economy_spend 键)", int(lr._spend_discounted(100)) == 100)
|
||||
lr.set_tree_rules(["economy_spend"])
|
||||
lr = load("res://core/level_runner.gd").new(_db, _fresh_rng(777005),
|
||||
{"tree_rules": ["economy_spend"]}) # 构造注入(拆件批 T3——setter 群退役)
|
||||
Kit.check("散激活:商品购买价 ×80%(provisional 折率——floor 偏向玩家、下限 1;刷新价不折=另一计价点零触碰)",
|
||||
int(lr._spend_discounted(100)) == 80 and int(lr._spend_discounted(1)) == 1)
|
||||
# 财富之道·聚:战斗掉落乘算·入账前(编排 _roll_gp_drop——同种子配对对拍 1.5×)
|
||||
|
||||
@@ -36,10 +36,10 @@ func _init() -> void:
|
||||
var e = load("res://core/adventure_runner.gd").new(db, load("res://core/rng_service.gd").new())
|
||||
e.start_adventure(501)
|
||||
e.stop()._pending = {"candidates": []}
|
||||
Kit.check_quiet(e.skip_empty_curio() and e.stop()._pending.is_empty(),
|
||||
Kit.check_quiet(e.stop().skip_empty_curio() and e.stop()._pending.is_empty(),
|
||||
"空配置闸:三选一池空=停点整体跳过(skip_empty_curio 消化)〔专长批 T10〕")
|
||||
e.stop()._pending = {"candidates": [{"kind": "gp", "tier": "common"}]}
|
||||
Kit.check_quiet(not e.skip_empty_curio(),
|
||||
Kit.check_quiet(not e.stop().skip_empty_curio(),
|
||||
"空配置闸反例:非空停点拒绝跳过(零自动推进契约不破)〔专长批 T10〕")
|
||||
var lr = load("res://core/level_runner.gd").new(db, load("res://core/rng_service.gd").new())
|
||||
lr.set_shop_pool([], Callable(), Callable(), Callable())
|
||||
@@ -69,7 +69,7 @@ func check_v7(a, db) -> void:
|
||||
Kit.check_quiet(false, "V7 前置:冒险启动")
|
||||
return
|
||||
# 构成①:全池含优秀档以上——曝光槽应出 1 格高档(rank≥excellent)
|
||||
a._curio_deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common"),
|
||||
a._curio.deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common"),
|
||||
_tok("armor", "common"), _tok("heal", "excellent"), _tok("refresh", "excellent"), _tok("ap", "rare")]
|
||||
var hi_seen := false
|
||||
for i in 40:
|
||||
@@ -84,7 +84,7 @@ func check_v7(a, db) -> void:
|
||||
hi_seen = true
|
||||
Kit.check_quiet(hi_seen, "曝光槽:全池含高档时三选一呈现 ≥1 格优秀档以上〔专长批 V7〕")
|
||||
# 构成②:高档子池空——该格回退全池(候选仍 3 格全普通)
|
||||
a._curio_deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common")]
|
||||
a._curio.deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common")]
|
||||
var ok_fb := true
|
||||
for i in 20:
|
||||
var cands2: Array = a.stop().draw_candidates("reward_node")
|
||||
@@ -96,7 +96,7 @@ func check_v7(a, db) -> void:
|
||||
ok_fb = false
|
||||
Kit.check_quiet(ok_fb, "子池空回退全池:全普通池候选恒 3 格普通档〔专长批 V7〕")
|
||||
# 构成③:凭证不进子池也不进全池视图(独立计数体系——只经专长凭证注入出现)
|
||||
a._curio_deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common"),
|
||||
a._curio.deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common"),
|
||||
_tok("feat_ticket", "excellent")]
|
||||
var ticket_seen := false
|
||||
for i in 30:
|
||||
@@ -105,7 +105,7 @@ func check_v7(a, db) -> void:
|
||||
ticket_seen = true
|
||||
Kit.check_quiet(not ticket_seen, "凭证不进抽签池(feat_ticket 只经保底注入通道)〔专长批 V7〕")
|
||||
# 构成④:池空=零候选合法态(同族兜底入口)
|
||||
a._curio_deck = []
|
||||
a._curio.deck = []
|
||||
Kit.check_quiet(a.stop().draw_candidates("reward_node").is_empty(), "池空=零候选合法态(skip_empty_curio 兜底入口)〔专长批 V7〕")
|
||||
|
||||
|
||||
@@ -114,26 +114,26 @@ func check_v6(b, db) -> void:
|
||||
Kit.check_quiet(false, "V6 前置:冒险启动")
|
||||
return
|
||||
# 拿了消耗:直置停点候选后 pick_curio——牌库摘牌单点
|
||||
b._curio_deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "excellent")]
|
||||
var gp_before: int = b.pool_stock("gp")
|
||||
b._curio.deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "excellent")]
|
||||
var gp_before: int = b.stop().pool_stock("gp")
|
||||
b.stop()._pending = {"candidates": [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "excellent")]}
|
||||
Kit.check_quiet(b.pick_curio("gp", "common") and b.pool_stock("gp") == gp_before - 1,
|
||||
Kit.check_quiet(b.stop().pick_curio("gp", "common") and b.stop().pool_stock("gp") == gp_before - 1,
|
||||
"拿了消耗:pick_curio 后牌库摘牌(选中踢池)〔专长批 V6〕")
|
||||
# 没拿回池:抽候选不摘牌——重复抽签同令牌可再现
|
||||
var deck_size: int = b._curio_deck.size()
|
||||
var deck_size: int = b._curio.deck.size()
|
||||
var seen_again := false
|
||||
for i in 30:
|
||||
var cands: Array = b.stop().draw_candidates("reward_node")
|
||||
if cands.size() == 2 and b._curio_deck.size() == deck_size:
|
||||
if cands.size() == 2 and b._curio.deck.size() == deck_size:
|
||||
seen_again = true
|
||||
Kit.check_quiet(seen_again, "没拿回池:抽签不摘牌(未选候选再次可现,牌库余量不变)〔专长批 V6〕")
|
||||
# 只刷出不计:抽签后 _curio_taken 零变化
|
||||
var taken_before: Dictionary = b._curio_taken.duplicate()
|
||||
var taken_before: Dictionary = b._curio.taken.duplicate()
|
||||
for i in 10:
|
||||
b.stop().draw_candidates("reward_node")
|
||||
var unchanged := true
|
||||
for k in taken_before.keys():
|
||||
if int(b._curio_taken.get(k, 0)) != int(taken_before[k]):
|
||||
if int(b._curio.taken.get(k, 0)) != int(taken_before[k]):
|
||||
unchanged = false
|
||||
Kit.check_quiet(unchanged, "只刷出不计:抽签不改已拿账〔专长批 V6〕")
|
||||
|
||||
@@ -163,21 +163,21 @@ func check_v8(c, db) -> void:
|
||||
# 概率位与 cap 两属性独立:改 cap 不动牌库(概率位)、改牌库不动 cap 字段
|
||||
var cap_field_before := int(db.adventure.curio_cap_gp)
|
||||
db.adventure.curio_cap_gp = 1 # 独立设 cap(概率位=gp 令牌数不动)
|
||||
var gp_tokens: int = c.pool_stock("gp")
|
||||
var gp_tokens: int = c.stop().pool_stock("gp")
|
||||
Kit.check_quiet(gp_tokens > 0 and int(db.adventure.curio_value("gp", "common")) == 20,
|
||||
"改 cap 不动概率位:牌库 gp 令牌 %d 枚在库、件值字段不受影响〔专长批 V8〕" % gp_tokens)
|
||||
# cap 只在拿了才计:刷出不计
|
||||
c._curio_deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common")]
|
||||
c._curio.deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common")]
|
||||
for i in 20:
|
||||
c.stop().draw_candidates("reward_node")
|
||||
Kit.check_quiet(bool(c._curio_cap_ok("gp", "")) and int(c._curio_taken.get("gp", 0)) == 0,
|
||||
Kit.check_quiet(bool(c._curio.cap_ok("gp", "")) and int(c._curio.taken.get("gp", 0)) == 0,
|
||||
"cap 刷出不计:20 次抽签后 gp 未拿、cap 未触发〔专长批 V8〕")
|
||||
# 拿了才计:pick 一次→cap 满→提前退役(候选视图剔除、牌库本体不动)
|
||||
c.stop()._pending = {"candidates": [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common")]}
|
||||
Kit.check_quiet(c.pick_curio("gp", "common"), "V8 前置:兑付 gp 一枚")
|
||||
Kit.check_quiet(not bool(c._curio_cap_ok("gp", "")), "cap 拿了才计:兑付后 cap 满(taken 1/1)〔专长批 V8〕")
|
||||
Kit.check_quiet(c.stop().pick_curio("gp", "common"), "V8 前置:兑付 gp 一枚")
|
||||
Kit.check_quiet(not bool(c._curio.cap_ok("gp", "")), "cap 拿了才计:兑付后 cap 满(taken 1/1)〔专长批 V8〕")
|
||||
var gp_in_deck := 0
|
||||
for t in c._curio_deck:
|
||||
for t in c._curio.deck:
|
||||
if String((t as Dictionary).get("kind", "")) == "gp":
|
||||
gp_in_deck += 1
|
||||
var gp_cand := false
|
||||
|
||||
@@ -117,7 +117,7 @@ func _init() -> void:
|
||||
adr5.set_save_manager(save_s.new("user://treasure_effects_p.json"))
|
||||
Kit.check_quiet(adr5.start_adventure(261, {"hero_override": {}, "treasure_unlocked": {}, "attunement": ["refresh_practice"]}),
|
||||
"刷新练习:装配冒险启动")
|
||||
Kit.check_quiet(int(adr5.refresh_stock()) == 1 and int(adr5.attune_refresh_left()) == 1,
|
||||
Kit.check_quiet(int(adr5.stop().refresh_stock()) == 1 and int(adr5.stop().attune_refresh_left()) == 1,
|
||||
"刷新练习:存量账 +1(装配即得一次性——attune_refresh_left 合计含 stock)")
|
||||
Kit.check_quiet(int(adr5.stop()._refresh_x) == 0,
|
||||
"刷新练习反例:临时账 X 不动(写临时账/重复加仓=违规形态)")
|
||||
@@ -219,7 +219,8 @@ func _init() -> void:
|
||||
var lv10 = load("res://core/level_runner.gd").new(db, load("res://core/rng_service.gd").new())
|
||||
Kit.check_quiet(int(lv10.shop_refresh_free_left()) == int(db.adventure.shop_refresh_free),
|
||||
"刷新执照基线:未装配=表值(%d)" % int(db.adventure.shop_refresh_free))
|
||||
lv10.set_attunement(["refresh_license"])
|
||||
lv10 = load("res://core/level_runner.gd").new(db, load("res://core/rng_service.gd").new(),
|
||||
{"attunement": ["refresh_license"]}) # 构造注入(拆件批 T3——setter 群退役)
|
||||
Kit.check_quiet(int(lv10.shop_refresh_free_left()) == int(db.adventure.shop_refresh_free) + 2,
|
||||
"刷新执照正常:免费刷新 +2/店(读数即本店可用——进店重置生命周期同 knob)")
|
||||
|
||||
|
||||
Reference in new issue
Block a user