KAZIK/tools/tests/artifacts_test.inc
Игорь Федосеев eaac8b861e feat: rework artifacts and tower relics
Extend profiles from 280 to 312 bytes with legacy compatibility.
Keep tower relics run-local and share the profile bankroll.
2026-10-30 23:22:19 +03:00

502 lines
14 KiB
PHP

; Native regression: real production procedures, isolated output paths.
.data
artifactTestPath3D db "build\artifacts\profile.dat",0
artifactTestDir3D db "build\artifacts",0
artifactTestPreview3D db "build\artifacts\preview.dat",0
artifactTestLegacy3D db "build\artifacts\legacy.dat",0
artifactTestProfileName3D db "profile.dat",0
artifactTestLegacyName3D db "legacy.dat",0
artifactTestBmp3D db "build\artifacts\shop.bmp",0
artifactTestRewardBmp3D db "build\artifacts\rewards.bmp",0
artifactTestHeader3D db 42h,4Dh
dd 1228854
dw 0,0
dd 54,40,640,-480
dw 1,32
dd 0,1228800,0,0,0,0
.code
ArtifactTestCapture3D PROC uses ebx path:DWORD
local io:DWORD
invoke CreateFileA,path,40000000h,0,0,2,80h,0
mov ebx,eax
invoke WriteFile,ebx,OFFSET artifactTestHeader3D,54,ADDR io,0
invoke WriteFile,ebx,OFFSET screenBuffer,SCREEN_SIZE*4,ADDR io,0
invoke CloseHandle,ebx
ret
ArtifactTestCapture3D ENDP
RunArtifactTest3D PROC uses ebx esi edi
local savedBank:DWORD,oldPath[260]:BYTE,io:DWORD
mov obsActive3D,0
mov tournamentMode,0
mov nativeProfileActive3D,0
mov arrivalConfirmed3D,0
call ResetArtifacts3D
mov bankroll,10000
invoke BuyMerchantCharm3D,0
cmp bankroll,9100
jne artifact_fail_1
cmp charmCloverUses,3
jne artifact_fail_1
invoke TriggerCharmLossProtection,100
cmp bankroll,9150
jne artifact_fail_1
cmp charmCloverUses,2
jne artifact_fail_1
invoke TriggerCharmLossProtection,0
cmp charmCloverUses,2
jne artifact_fail_1
mov charmHorseshoeUses,5
invoke TriggerCharmWinBonus,1000
cmp eax,350
jne artifact_fail_2
cmp bankroll,9500
jne artifact_fail_2
mov charmDevilUses,2
invoke ToggleArtifact3D,3
cmp charmEnabledMask3D,12
jne artifact_fail_2
invoke TriggerCharmWinBonus,100
cmp eax,100
jne artifact_fail_2
cmp charmDevilUses,1
jne artifact_fail_2
invoke TriggerCharmLossProtection,100
cmp eax,0
jne artifact_fail_2
cmp charmDevilUses,0
jne artifact_fail_2
mov charmEnabledMask3D,7
mov bankroll,999999999
invoke TriggerCharmWinBonus,1000000000
cmp eax,1
jne artifact_fail_3
cmp bankroll,1000000000
jne artifact_fail_3
mov eax,charmHorseshoeUses
mov ebx,eax
invoke TriggerCharmWinBonus,100
cmp charmHorseshoeUses,ebx
jne artifact_fail_3
mov charmSkullUses,1
mov obsActive3D,1
invoke TriggerCharmBulletProtection
test eax,eax
jnz artifact_fail_4
cmp charmSkullUses,1
jne artifact_fail_4
mov obsActive3D,0
mov tournamentMode,1
invoke TriggerCharmLossProtection,100
test eax,eax
jnz artifact_fail_4
invoke TriggerCharmBulletProtection
test eax,eax
jnz artifact_fail_4
mov towerBulletUses3D,1
invoke TriggerCharmBulletProtection
cmp eax,1
jne artifact_fail_4
cmp charmSkullUses,1
jne artifact_fail_4
cmp towerBulletUses3D,0
jne artifact_fail_4
mov tournamentMode,0
mov charmCloverUses,98
mov bankroll,10000
invoke BuyMerchantCharm3D,0
cmp bankroll,10000
jne artifact_fail_5
cmp charmCloverUses,98
jne artifact_fail_5
mov charmCloverUses,0
mov bankroll,0
invoke BuyMerchantCharm3D,0
cmp charmCloverUses,0
jne artifact_fail_5
; Reward cannot be claimed twice; reset starts a fresh run without touching bank.
mov bankroll,10000
mov towerStage,1
mov towerFloorState,TOWER_STATE_BRIEFING
call ResetTowerRelics3D
call PrepareTowerReward3D
invoke ChooseTowerRelic3D,0
invoke ChooseTowerRelic3D,0
cmp towerHeartUses3D,1
jne artifact_fail_6
mov tournamentMode,1
mov towerFloorState,TOWER_STATE_IN_GAME
invoke TowerReportRoundOutcome,2
cmp towerFloorState,TOWER_STATE_BRIEFING
jne artifact_fail_6
cmp towerHeartUses3D,0
jne artifact_fail_6
; Duplicate report cannot kill a saved attempt.
invoke TowerReportRoundOutcome,2
cmp towerFloorState,TOWER_STATE_BRIEFING
jne artifact_fail_6
mov towerFloorState,TOWER_STATE_IN_GAME
invoke TowerReportRoundOutcome,1
cmp towerRewardPending3D,1
jne artifact_fail_6
invoke ChooseTowerRelic3D,1
cmp towerSealStage3D,2
jne artifact_fail_6
cmp towerSealUses3D,2
jne artifact_fail_6
mov towerStage,2
mov towerFloorState,TOWER_STATE_IN_GAME
invoke TowerReportRoundOutcome,2
cmp towerSealUses3D,1
jne artifact_fail_6
cmp towerFloorState,TOWER_STATE_BRIEFING
jne artifact_fail_6
call ResetTowerRelics3D
cmp towerSealUses3D,0
jne artifact_fail_6
cmp bankroll,10000
jne artifact_fail_6
; Exact net loss refunded, not arbitrary prize or a second stake payout.
mov towerPurseUses3D,1
mov towerHeartUses3D,1
mov towerEntryBank3D,10000
mov bankroll,9900
mov towerFloorState,TOWER_STATE_IN_GAME
invoke TowerReportRoundOutcome,2
cmp bankroll,10000
jne artifact_fail_6
cmp towerPurseUses3D,0
jne artifact_fail_6
mov towerStage,6
mov towerFloorState,TOWER_STATE_IN_GAME
invoke TowerReportRoundOutcome,1
mov eax,bankroll
mov savedBank,eax
invoke TowerReportRoundOutcome,1
mov eax,savedBank
cmp bankroll,eax
jne artifact_fail_6
cmp towerHeartUses3D,0
jne artifact_fail_6
; Bust protection removes the real last card, without drawing a replacement.
mov towerBustUses3D,1
mov cbPlayerCount3D,3
mov cbPlayer3D,8
mov cbPlayer3D[4],7
mov cbPlayer3D[8],6
call TryTowerBustSave3D
cmp eax,1
jne artifact_fail_7
cmp cbPlayerCount3D,2
jne artifact_fail_7
cmp cbPlayerScore3D,19
jne artifact_fail_7
mov towerEye3D,1
mov bs3d_shellIndex,0
mov bs3d_shellCount,2
mov bs3d_shells,1
call UpdateTowerEye3D
cmp bs3d_known,1
jne artifact_fail_7
mov tournamentMode,0
call ResetTowerRelics3D
; Both legacy checksum and versioned extension must validate.
mov DWORD PTR [saveBuffer+280],32465241h
mov DWORD PTR [saveBuffer+284],3
mov DWORD PTR [saveBuffer+288],5
mov DWORD PTR [saveBuffer+292],1
mov DWORD PTR [saveBuffer+296],2
mov DWORD PTR [saveBuffer+300],7
mov DWORD PTR [saveBuffer+304],2
invoke ArtifactSaveSignature3D,OFFSET saveBuffer
mov DWORD PTR [saveBuffer+308],eax
invoke ValidateArtifactSave3D,OFFSET saveBuffer
cmp eax,1
jne artifact_fail_8
inc DWORD PTR [saveBuffer+284]
invoke ValidateArtifactSave3D,OFFSET saveBuffer
test eax,eax
jnz artifact_fail_8
; Real profile write/reload uses test paths, never runtime/profiles.
invoke CreateDirectoryA,OFFSET artifactTestDir3D,0
mov nativeProfilesDirPtr3D,OFFSET artifactTestDir3D
mov nativeProfileActive3D,1
invoke CopyCString,OFFSET saveFileName,OFFSET artifactTestProfileName3D
mov charmCloverUses,3
mov charmHorseshoeUses,5
mov charmSkullUses,1
mov charmDevilUses,2
mov charmEnabledMask3D,7
mov bankroll,12345
call SaveGraphicProfile3D
invoke ValidateGraphicProfile3D,OFFSET artifactTestPath3D
cmp eax,1
jne artifact_fail_9
call ResetArtifacts3D
mov bankroll,0
call LoadSave
cmp bankroll,12345
jne artifact_fail_9
cmp charmCloverUses,3
jne artifact_fail_9
cmp charmDevilUses,2
jne artifact_fail_9
cmp charmEnabledMask3D,7
jne artifact_fail_9
; A signed 280-byte legacy file imports with an empty artifact inventory.
invoke CreateFileA,OFFSET artifactTestLegacy3D,40000000h,0,0,2,80h,0
mov ebx,eax
invoke WriteFile,ebx,OFFSET saveBuffer,SAVE_LEGACY_SIZE,ADDR io,0
invoke CloseHandle,ebx
invoke ValidateGraphicProfile3D,OFFSET artifactTestLegacy3D
cmp eax,1
jne artifact_fail_9
invoke CopyCString,OFFSET saveFileName,OFFSET artifactTestLegacyName3D
call LoadSave
cmp charmCloverUses,0
jne artifact_fail_9
cmp bankroll,12345
jne artifact_fail_9
; Preview format roundtrip, disabled effects and checksum rejection.
mov nativeProfileActive3D,0
invoke CopyCString,OFFSET savePath3D,OFFSET artifactTestPreview3D
mov arrivalConfirmed3D,1
mov bankroll,54321
mov charmCloverUses,9
mov charmHorseshoeUses,8
mov charmSkullUses,7
mov charmDevilUses,6
mov charmEnabledMask3D,4
call SaveProgress3D
mov arrivalConfirmed3D,0
call ResetArtifacts3D
call LoadProgress3D
cmp bankroll,54321
jne artifact_fail_10
cmp charmCloverUses,9
jne artifact_fail_10
cmp charmDevilUses,6
jne artifact_fail_10
cmp charmEnabledMask3D,4
jne artifact_fail_10
invoke TriggerCharmWinBonus,100
test eax,eax
jnz artifact_fail_10
cmp charmHorseshoeUses,8
jne artifact_fail_10
inc saveData3D[16]
invoke CreateFileA,OFFSET artifactTestPreview3D,40000000h,0,0,2,80h,0
mov ebx,eax
invoke WriteFile,ebx,OFFSET saveData3D,40,ADDR io,0
invoke CloseHandle,ebx
call LoadProgress3D
cmp bankroll,10000
jne artifact_fail_10
cmp charmCloverUses,0
jne artifact_fail_10
call ResetProfileDefaults
cmp charmSkullUses,0
jne artifact_fail_10
; Production Buckshot settlement pays net-profit bonus and cannot repeat it.
mov bankroll,9900
mov charmEnabledMask3D,7
mov charmHorseshoeUses,2
mov bs3d_bet,100
mov bs3d_state,BS_SHOT
mov bs3d_afterAnim,BS_WIN
call FinishBuckshotAction3D
cmp bankroll,10270
jne artifact_fail_11
cmp charmHorseshoeUses,1
jne artifact_fail_11
call FinishBuckshotAction3D
cmp bankroll,10270
jne artifact_fail_11
mov bankroll,9900
mov charmCloverUses,2
mov bs3d_state,BS_SHOT
mov bs3d_afterAnim,BS_LOSE
call FinishBuckshotAction3D
cmp bankroll,9950
jne artifact_fail_11
cmp charmCloverUses,1
jne artifact_fail_11
; Keyboard purchase requires two presses; selection cancels confirmation.
mov bankroll,10000
call ResetArtifacts3D
mov merchantTab3D,1
mov merchantCharmSelected3D,0
mov artifactBuyArmed3D,0
call ClearKeys3D
mov pressedKeys3D[0Dh],1
call HandleArtifactShop3D
cmp bankroll,10000
jne artifact_fail_12
cmp artifactBuyArmed3D,1
jne artifact_fail_12
mov pressedKeys3D[0Dh],1
call HandleArtifactShop3D
cmp bankroll,9100
jne artifact_fail_12
cmp charmCloverUses,3
jne artifact_fail_12
mov artifactBuyArmed3D,1
mov pressedKeys3D[28h],1
call HandleArtifactShop3D
cmp artifactBuyArmed3D,0
jne artifact_fail_12
cmp merchantCharmSelected3D,1
jne artifact_fail_12
mov pressedKeys3D[09h],1
call HandleArtifactShop3D
cmp merchantTab3D,0
jne artifact_fail_12
; Fresh run clears every relic, stale offer and entry bankroll.
mov towerHeartUses3D,5
mov towerSealUses3D,2
mov towerSealStage3D,6
mov towerBulletUses3D,2
mov towerBustUses3D,2
mov towerEye3D,1
mov towerPurseUses3D,2
call ResetTowerRelics3D
mov eax,towerHeartUses3D
or eax,towerSealUses3D
or eax,towerSealStage3D
or eax,towerBulletUses3D
or eax,towerBustUses3D
or eax,towerEye3D
or eax,towerPurseUses3D
or eax,towerEntryBank3D
or eax,towerRewardPending3D
test eax,eax
jnz artifact_fail_12
; Leaving each native table must end the run, not leak tournament mode to hall.
mov tournamentMode,1
mov towerHeartUses3D,1
mov dice3d_state,0
call DiceEscape3D
cmp tournamentMode,0
jne artifact_fail_13
cmp towerHeartUses3D,0
jne artifact_fail_13
mov tournamentMode,1
mov towerEye3D,1
mov roulState,0
call WheelEscape3D
cmp tournamentMode,0
jne artifact_fail_13
cmp towerEye3D,0
jne artifact_fail_13
mov tournamentMode,1
mov towerBustUses3D,1
mov engineMode,MODE_BLACKJACK
mov cbState3D,CB_IDLE
call LeaveCardTable3D
cmp tournamentMode,0
jne artifact_fail_13
cmp towerBustUses3D,0
jne artifact_fail_13
mov tournamentMode,1
mov towerPurseUses3D,1
mov bankroll,9950
mov coin3d_bet,50
mov coin3d_state,COIN_TOSS
mov coin3d_choice,1
mov coin3d_result,1
call CoinEscape3D
cmp bankroll,10050
jne artifact_fail_13
cmp tournamentMode,0
jne artifact_fail_13
cmp towerPurseUses3D,0
jne artifact_fail_13
call CoinSettle3D
cmp bankroll,10050
jne artifact_fail_13
; Situational offers follow the upcoming floor, not the one just cleared.
mov towerStage,2
mov towerFloorState,TOWER_STATE_CLEAR
call PrepareTowerReward3D
cmp towerRewardOffers3D[4],3
jne artifact_fail_14
mov towerStage,3
call PrepareTowerReward3D
cmp towerRewardOffers3D[4],2
jne artifact_fail_14
mov towerStage,5
call PrepareTowerReward3D
cmp towerRewardOffers3D[4],4
jne artifact_fail_14
invoke ChooseTowerRelic3D,1
cmp towerEye3D,1
jne artifact_fail_14
call ResetTowerRelics3D
; Render shipping UI; captures inspected by the Python runner.
mov merchantTab3D,1
mov merchantCharmSelected3D,0
mov merchantMessage3D,0
call RenderMerchant3D
invoke ArtifactTestCapture3D,OFFSET artifactTestBmp3D
mov towerStage,3
mov engineMode,MODE_HELL_TOWER
mov towerFloorState,TOWER_STATE_BRIEFING
call PrepareTowerReward3D
call RenderHellTower3D
invoke ArtifactTestCapture3D,OFFSET artifactTestRewardBmp3D
xor eax,eax
ret
artifact_fail_1:
mov eax,101
ret
artifact_fail_2:
mov eax,102
ret
artifact_fail_3:
mov eax,103
ret
artifact_fail_4:
mov eax,104
ret
artifact_fail_5:
mov eax,105
ret
artifact_fail_6:
mov eax,106
ret
artifact_fail_7:
mov eax,107
ret
artifact_fail_8:
mov eax,108
ret
artifact_fail_9:
mov eax,109
ret
artifact_fail_10:
mov eax,110
ret
artifact_fail_11:
mov eax,111
ret
artifact_fail_12:
mov eax,112
ret
artifact_fail_13:
mov eax,113
ret
artifact_fail_14:
mov eax,114
ret
RunArtifactTest3D ENDP