@@ -1025,17 +1025,17 @@ func _smoke_shop_room() -> void:
return
Kit . check ( " 到店开店态(覆盖层数据源就位——离开前不出选路口,零自动推进) " , not runner . awaiting_choice ( ) and runner . next_candidate_ids ( ) . is_empty ( ) )
# 现价 = 基价 + price_level_bonus(L2)=2 + 步长 × 已购档数
var prods : Array = runner . shop_products ( )
var prods : Array = runner . shop . shop_products ( )
Kit . check ( " 三商品全陈列(atk_up/hp_up/armor_up——无刷新无摇号) " , prods . size ( ) == 3 )
var by_id := _shop_products_by_id ( prods )
Kit . check ( " L2 首购现价 = 基价 + 关级加值 2( atk_up 6 / hp_up 4 / armor_up 6) " , int ( by_id [ " atk_up " ] [ " price " ] ) == 6 and int ( by_id [ " hp_up " ] [ " price " ] ) == 4 and int ( by_id [ " armor_up " ] [ " price " ] ) == 6 )
# 购买 atk_up:钱包 −6 · 加算区 atk +1 · 二购现价 8
var gp0 : int = runner . gp
Kit . check ( " 购买 atk_up 受理(现价 6) " , runner . buy_product ( " atk_up " ) )
Kit . check ( " 购买 atk_up 受理(现价 6) " , runner . shop . buy_product ( " atk_up " ) )
Kit . check ( " 钱包扣现价 6( %d → %d ) " % [ gp0 , runner . gp ] , runner . gp == gp0 - 6 )
# 加算区住加算日记
Kit . check ( " 统一冒险加算区 atk +1(加算区住加算日记) " , runner . journal ( ) . bonus_total ( " atk " ) == 1 and runner . journal ( ) . bonus_total ( " max_hp " ) == 0 and runner . journal ( ) . bonus_total ( " armor_class " ) == 0 )
by_id = _shop_products_by_id ( runner . shop_products ( ) )
by_id = _shop_products_by_id ( runner . shop . shop_products ( ) )
Kit . check ( " atk_up 二购现价 = 4+2+2=8(步长 2 × 已购 1 档,现价现算) " , int ( by_id [ " atk_up " ] [ " price " ] ) == 8 and int ( by_id [ " atk_up " ] [ " purchased " ] ) == 1 )
# 行进段百分比归零(购买/生效断言按加算区裸值口径——调试浮窗百分比后乘;hp 快照钳到新口径上限防 spawn 越界,测试通道)
runner . set_hero_override ( 0 , 0 )
@@ -1043,28 +1043,28 @@ func _smoke_shop_room() -> void:
# hp_up:上限与当前生命同步 +3(封顶新上限)
var hp_before : int = runner . hero_hp
var mhp_before : int = runner . effective_max_hp ( )
Kit . check ( " 购买 hp_up 受理(现价 4) " , runner . buy_product ( " hp_up " ) )
Kit . check ( " 购买 hp_up 受理(现价 4) " , runner . shop . buy_product ( " hp_up " ) )
Kit . check ( " 钱包扣 4( %d ) " % runner . gp , runner . gp == gp0 - 6 - 4 )
Kit . check ( " 生命上限 +3( %d → %d ——加算区 max_hp 轴) " % [ mhp_before , runner . effective_max_hp ( ) ] , runner . effective_max_hp ( ) == mhp_before + 3 )
Kit . check ( " 当前生命同步 +3 封顶新上限( %d → %d ) " % [ hp_before , runner . hero_hp ] , runner . hero_hp == mini ( hp_before + 3 , runner . effective_max_hp ( ) ) )
# armor_up: AC 10+1
Kit . check ( " 购买 armor_up 受理(现价 6) " , runner . buy_product ( " armor_up " ) )
Kit . check ( " 购买 armor_up 受理(现价 6) " , runner . shop . buy_product ( " armor_up " ) )
Kit . check ( " AC = 10+1( armor_class 加算区轴,无百分比通道) " , runner . effective_ac ( ) == int ( _db . combat . hero . armor_class ) + 1 )
# 余额不足购买被拒(零副作用):hp_up 连购至不可负担后兜底拒绝
var guard_drain := 20
var hp_buys := 1 # 夹具前段已购 1 笔(购买 hp_up 受理断言)——总数 = 前段 + 本循环
while guard_drain > 0 :
guard_drain - = 1
var hp_price : int = int ( _shop_products_by_id ( runner . shop_products ( ) ) [ " hp_up " ] [ " price " ] )
var hp_price : int = int ( _shop_products_by_id ( runner . shop . shop_products ( ) ) [ " hp_up " ] [ " price " ] )
if runner . gp < hp_price :
break
if not runner . buy_product ( " hp_up " ) :
if not runner . shop . buy_product ( " hp_up " ) :
break
hp_buys + = 1
var gp_dry : int = runner . gp
var tier_dry : int = runner . purchased_tier ( " hp_up " )
var hp_dry : int = int ( _shop_products_by_id ( runner . shop_products ( ) ) [ " hp_up " ] [ " price " ] )
Kit . check ( " 余额不足购买被拒(gp= %d < 现价 %d ——零扣费零档位变动) " % [ gp_dry , hp_dry ] , not runner . buy_product ( " hp_up " ) and runner . gp == gp_dry and runner . purchased_tier ( " hp_up " ) == tier_dry )
var tier_dry : int = runner . shop . purchased_tier ( " hp_up " )
var hp_dry : int = int ( _shop_products_by_id ( runner . shop . shop_products ( ) ) [ " hp_up " ] [ " price " ] )
Kit . check ( " 余额不足购买被拒(gp= %d < 现价 %d ——零扣费零档位变动) " % [ gp_dry , hp_dry ] , not runner . shop . buy_product ( " hp_up " ) and runner . gp == gp_dry and runner . shop . purchased_tier ( " hp_up " ) == tier_dry )
# 离开 → 回选路口(候选 = 该店出边——恰一条,指向终点 Boss)
Kit . check ( " 离开商店 → 回选路口(候选 = 店出边 %s ——零自动推进收口) " % str ( shop_outs ) ,
runner . continue_after_node ( ) and runner . awaiting_choice ( ) and _sorted_ids ( runner . next_candidate_ids ( ) ) == _sorted_ids ( shop_outs ) )
@@ -1253,7 +1253,7 @@ func _smoke_shop_pool() -> void:
if not _adv_drive_to_shop ( a8 , _adv_st ( ) , autoplay ) :
continue
scen = { " a " : a8 , " s " : s , " r " : a8 . runner ( ) }
first_shelf_a = ( a8 . runner ( ) . shop_shelf ( ) as Array ) . duplicate ( true )
first_shelf_a = ( a8 . runner ( ) . shop . shop_shelf ( ) as Array ) . duplicate ( true )
break
Kit . check ( " 池模式商店房场景可达(seed= %s ) " % str ( scen . get ( " s " , - 1 ) ) , not scen . is_empty ( ) )
if not scen . is_empty ( ) :
@@ -1262,19 +1262,19 @@ func _smoke_shop_pool() -> void:
a8b . set_hero_override ( 900 , 400 )
if a8b . start_adventure ( int ( scen [ " s " ] ) , { " shop_mode " : " pool " } ) \
and _adv_drive_to_shop ( a8b , _adv_st ( ) , autoplay ) :
first_shelf_b = ( a8b . runner ( ) . shop_shelf ( ) as Array ) . duplicate ( true )
first_shelf_b = ( a8b . runner ( ) . shop . shop_shelf ( ) as Array ) . duplicate ( true )
Kit . check ( " 进店抽 3(货架 %d 卡——同构交互) " % first_shelf_a . size ( ) , first_shelf_a . size ( ) == 3 )
# MC-1 商店独立刷新(P-C2+Q2 裁——基础免费 0; GP 刷新 ceil(20× 1.8^n) provisional;重抽同源)
if not scen . is_empty ( ) :
var r8 = scen [ " r " ]
var gp0 : int = int ( r8 . gp )
var cost0 : int = r8 . shop_refresh_cost ( )
var cost0 : int = r8 . shop . shop_refresh_cost ( )
Kit . check ( " 刷新首价=基价( %d ) " % cost0 , cost0 == int ( _db . run . adventure . shop_refresh_cost_base ) )
Kit . check ( " 基础免费 0 次(Q2——天赋增益位后续添加) " , r8 . shop_refresh_free_left ( ) == 0 )
var shelf_pre : Array = ( r8 . shop_shelf ( ) as Array ) . duplicate ( true )
Kit . check ( " GP 刷新受理(gp= %d cost= %d ) " % [ gp0 , cost0 ] , r8 . shop_refresh ( ) )
Kit . check ( " 基础免费 0 次(Q2——天赋增益位后续添加) " , r8 . shop . shop_refresh_free_left ( ) == 0 )
var shelf_pre : Array = ( r8 . shop . shop_shelf ( ) as Array ) . duplicate ( true )
Kit . check ( " GP 刷新受理(gp= %d cost= %d ) " % [ gp0 , cost0 ] , r8 . shop . shop_refresh ( ) )
Kit . check ( " GP 刷新扣费( %d → %d ) " % [ gp0 , int ( r8 . gp ) ] , int ( r8 . gp ) == gp0 - cost0 )
Kit . check ( " 刷新爬价 × curve( %d ) " % int ( r8 . shop_refresh_cost ( ) ) , int ( r8 . shop_refresh_cost ( ) ) == int ( ceil ( float ( cost0 ) * float ( _db . run . adventure . shop_refresh_cost_curve ) ) ) )
Kit . check ( " 刷新爬价 × curve( %d ) " % int ( r8 . shop . shop_refresh_cost ( ) ) , int ( r8 . shop . shop_refresh_cost ( ) ) == int ( ceil ( float ( cost0 ) * float ( _db . run . adventure . shop_refresh_cost_curve ) ) ) )
var same_shelf := first_shelf_a . size ( ) == first_shelf_b . size ( )
if same_shelf :
for i in first_shelf_a . size ( ) :
@@ -1290,10 +1290,10 @@ func _smoke_shop_pool() -> void:
# ② 货架投影形制:kind 词表封闭 + 现价公式推导(ceil(base×b^(关序−1)×A^0)——核心现算,呈现零复算)
var l2 := int ( r8 . level_row . level_index )
# 现价等价证明(d11——消费端读表推导 vs 迁移前硬编码字面量推导:同输入逐位一致)
var relic_price_now : int = r8 . pool_price ( " relic " )
var relic_price_now : int = r8 . shop . pool_price ( " relic " )
var relic_price_pre : int = int ( ceil ( 15.0 * pow ( _db . run . shop . price_b , float ( l2 - 1 ) ) * 1.0 ) )
Kit . check ( " relic 现价 = ceil(15.0× b^(关序−1))(读表与迁移前字面量逐位一致, %d )〔wd11〕 " % relic_price_now , relic_price_now == relic_price_pre )
for c in r8 . shop_shelf ( ) :
for c in r8 . shop . shop_shelf ( ) :
# T6 商店保底后 relic 卡合法入架(保底占位)——词表断言放行 relic;价格断言分叉
# (数值卡走 shop_pool_row 推导 / relic 卡走表 knob relic_base_price——同公式不同基价)
var ckind := String ( c . get ( " kind_id " , " " ) )
@@ -1308,7 +1308,7 @@ func _smoke_shop_pool() -> void:
Kit . check ( " 首购现价 = ceil(基价×b^(关序−1))( %s : %d = %d 推导) " % [ ckind , int ( c . get ( " price " , - 1 ) ) , expect_p ] , int ( c . get ( " price " , - 1 ) ) == expect_p )
# ③ 买 1 全重抽:出账+加算区+账本三落点 + 现价 A 链递增(买后 visit 计数=1;TP0——消费在架令牌本体)
var buy_c : Dictionary = { }
for c in r8 . shop_shelf ( ) :
for c in r8 . shop . shop_shelf ( ) :
if int ( c . get ( " price " , 1 << 30 ) ) < = int ( r8 . gp ) :
buy_c = c
break
@@ -1320,7 +1320,7 @@ func _smoke_shop_pool() -> void:
var gp0 : int = int ( r8 . gp )
var taken0 : int = int ( a8 . _curio . taken . get ( kind , 0 ) )
var val0 : int = a8 . journal ( ) . bonus_total ( String ( val_map [ kind ] ) )
Kit . check ( " 购买受理(pool 口—— %s | %s ) " % [ kind , tier ] , r8 . buy_pool_item ( kind ) )
Kit . check ( " 购买受理(pool 口—— %s | %s ) " % [ kind , tier ] , r8 . shop . 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 . run . adventure . curio_value ( kind , tier ) ) ] , a8 . journal ( ) . bonus_total ( String ( val_map [ kind ] ) ) == val0 + int ( _db . run . adventure . curio_value ( kind , tier ) ) )
Kit . check ( " 共享池账本 -1(跨渠道单点——taken %d → %d ) " % [ taken0 , int ( a8 . deck ( ) . taken . get ( kind , 0 ) ) ] , int ( a8 . deck ( ) . taken . get ( kind , 0 ) ) == taken0 + 1 )
@@ -1328,7 +1328,7 @@ func _smoke_shop_pool() -> void:
# A 链:白盒抬 GP 保证第二购场景确定构造(直改测试基建——非生产行为)
r8 . gp = int ( r8 . gp ) + 64
var second : Dictionary = { }
for c in r8 . shop_shelf ( ) :
for c in r8 . shop . shop_shelf ( ) :
if int ( c . get ( " price " , 1 << 30 ) ) < = int ( r8 . gp ) :
second = c
break
@@ -1336,14 +1336,14 @@ func _smoke_shop_pool() -> void:
var prow2 : Dictionary = _db . run . shop . pool_row ( String ( second . get ( " kind_id " , " " ) ) )
var expect_p2 : int = int ( ceil ( float ( int ( prow2 . get ( " base_price " , 0 ) ) ) * pow ( _db . run . shop . price_b , float ( l2 - 1 ) ) * _db . run . shop . price_a ) )
Kit . check ( " A 链爬价 = ceil(base× b^(关序−1)× A^1)(进店第 2 购—— %d ) " % expect_p2 , int ( second . get ( " price " , - 1 ) ) == expect_p2 )
Kit . check ( " 同 visit 第二购受理(A 链软闸在价不在限) " , r8 . buy_pool_item ( String ( second . get ( " kind_id " , " " ) ) ) )
Kit . check ( " 同 visit 第二购受理(A 链软闸在价不在限) " , r8 . shop . buy_pool_item ( String ( second . get ( " kind_id " , " " ) ) ) )
else :
Kit . check ( " A 链爬价场景未构造(抬 GP 后货架仍无可购第二卡)——场景绑定失败 " , false )
# ④ 切边零入店(白-box 重抽 40 次——GP 袋/规则改写型特性永不在架;重抽消费 shop_draw 签,场景尾不回写主时间线)
var cut_seen := false
for i in 40 :
r8 . _shop_draw_shelf ( )
for c in r8 . shop_shelf ( ) :
r8 . shop . _draw_shelf ( )
for c in r8 . shop . shop_shelf ( ) :
if String ( c . get ( " kind_id " , " " ) ) == " gp " or String ( c . get ( " kind_id " , " " ) ) == " treasure_item " :
cut_seen = true
Kit . check ( " 切边件零入店(40 次重抽零 gp/aux——负交易切边+三轴 doctrine) " , not cut_seen )
@@ -1353,8 +1353,8 @@ func _smoke_shop_pool() -> void:
a8 . _curio . deck . remove_at ( di8 )
var attack_seen := false
for i in 40 :
r8 . _shop_draw_shelf ( )
if ( r8 . shop_shelf ( ) as Array ) . any ( func ( c ) : return String ( c . get ( " kind_id " , " " ) ) == " attack " ) :
r8 . shop . _draw_shelf ( )
if ( r8 . shop . shop_shelf ( ) as Array ) . any ( func ( c ) : return String ( c . get ( " kind_id " , " " ) ) == " attack " ) :
attack_seen = true
break
Kit . check ( " 库存尽剔牌库(attack 令牌耗尽——池消耗即上限跨渠道共库 reward→shop 向) " , not attack_seen )