.data coinTestStage3D dd 0 coinTestRates3D dd 8,16,33,250 coinTestTimes3D dd 0,180,300,420,600,900,1020,1110,1700 coinTest0 db "build\actions\coin-idle.bmp",0 coinTest1 db "build\actions\coin-hold.bmp",0 coinTest2 db "build\actions\coin-release.bmp",0 coinTest3 db "build\actions\coin-air.bmp",0 coinTest4 db "build\actions\coin-apex.bmp",0 coinTest5 db "build\actions\coin-descent.bmp",0 coinTest6 db "build\actions\coin-land.bmp",0 coinTest7 db "build\actions\coin-bounce.bmp",0 coinTest8 db "build\actions\coin-result.bmp",0 coinTest9 db "build\actions\coin-tails.bmp",0 coinTestPaths3D dd OFFSET coinTest0,OFFSET coinTest1,OFFSET coinTest2 dd OFFSET coinTest3,OFFSET coinTest4,OFFSET coinTest5 dd OFFSET coinTest6,OFFSET coinTest7,OFFSET coinTest8 .code RunCoinTest3D PROC uses ebx esi edi local oldBank:DWORD,oldSeed:DWORD,oldMode:DWORD,oldDelta:DWORD local expected:DWORD,seedSnapshot:DWORD,ticks:DWORD,total:DWORD,iterations:DWORD local pointer:DWORD,previousX:DWORD,previousY:DWORD mov eax,bankroll mov oldBank,eax mov eax,rngSeed3D mov oldSeed,eax mov eax,engineMode mov oldMode,eax mov eax,deltaTime3D mov oldDelta,eax call ClearKeys3D mov mouseClick3D,0 mov bankroll,100000 mov coinTestStage3D,1 mov engineMode,MODE_WALK mov interactTargetId,INTERACT_COIN call Trigger3DInteraction cmp engineMode,MODE_COIN jne coin_test_fail cmp coinArtReady3D,1 jne coin_test_fail cmp coinHandsArt3D.frames,16 jne coin_test_fail mov eax,coinTableArt3D.pixels mov pointer,eax call InitCoinGame mov eax,pointer cmp coinTableArt3D.pixels,eax jne coin_test_fail ; Missing packs and insufficient funds cannot consume a wager or RNG. mov coinTestStage3D,2 call FreeNativeCoinArt3D mov BYTE PTR coinHandsPath3D,'!' call InitCoinGame mov BYTE PTR coinHandsPath3D,'a' test eax,eax jnz coin_test_fail cmp coinArtReady3D,0 jne coin_test_fail cmp coinTableArt3D.pixels,0 jne coin_test_fail mov eax,rngSeed3D mov seedSnapshot,eax mov pressedKeys3D[20h],1 call HandleCoinInput cmp bankroll,100000 jne coin_test_fail mov eax,seedSnapshot cmp rngSeed3D,eax jne coin_test_fail call InitCoinGame test eax,eax jz coin_test_fail mov bankroll,49 mov coin3d_bet,50 mov pressedKeys3D[20h],1 call HandleCoinInput cmp bankroll,49 jne coin_test_fail cmp coinError3D,1 jne coin_test_fail cmp coin3d_state,COIN_IDLE jne coin_test_fail mov eax,seedSnapshot cmp rngSeed3D,eax jne coin_test_fail ; Bounds, face choices and edge-consumed controls use the real handler. mov coinTestStage3D,3 mov pressedKeys3D[53h],1 call HandleCoinInput cmp coin3d_bet,50 jne coin_test_fail mov coin3d_bet,5000 mov pressedKeys3D[57h],1 call HandleCoinInput cmp coin3d_bet,5000 jne coin_test_fail mov coin3d_bet,100 mov mouseX3D,124 mov mouseY3D,204 mov mouseClick3D,1 call HandleCoinInput cmp coin3d_bet,50 jne coin_test_fail mov mouseX3D,148 mov mouseClick3D,1 call HandleCoinInput cmp coin3d_bet,100 jne coin_test_fail call HandleCoinInput cmp coin3d_bet,100 jne coin_test_fail mov mouseX3D,150 mov mouseY3D,226 mov mouseClick3D,1 call HandleCoinInput cmp coin3d_choice,2 jne coin_test_fail mov pressedKeys3D[31h],1 call HandleCoinInput cmp coin3d_choice,1 jne coin_test_fail ; Five hundred paid flips, both outcomes and both choices, four frame rates. mov coinTestStage3D,4 mov iterations,500 coin_test_round: mov bankroll,100000 mov coin3d_state,COIN_IDLE mov coin3d_timer,0 mov coin3d_bet,100 mov engineMode,MODE_COIN mov eax,iterations and eax,1 inc eax mov coin3d_choice,eax mov pressedKeys3D[20h],1 call HandleCoinInput cmp coin3d_state,COIN_TOSS jne coin_test_fail cmp bankroll,99900 jne coin_test_fail mov eax,iterations shr eax,1 and eax,1 inc eax mov coin3d_result,eax mov expected,99900 cmp eax,coin3d_choice jne @F mov expected,100100 @@: mov eax,rngSeed3D mov seedSnapshot,eax mov eax,iterations and eax,3 mov eax,coinTestRates3D[eax*4] mov deltaTime3D,eax mov ticks,0 mov total,0 ; Half the rounds request Escape before the toss completes. test iterations,1 jz coin_test_tick call CardTableEscape3D cmp eax,1 jne coin_test_fail cmp engineMode,MODE_COIN jne coin_test_fail cmp coinExitQueued3D,1 jne coin_test_fail coin_test_tick: call HandleCoinInput inc ticks mov eax,deltaTime3D add total,eax cmp ticks,326 ja coin_test_fail cmp coin3d_state,COIN_TOSS je coin_test_tick cmp coin3d_state,COIN_RESULT jne coin_test_fail cmp coin3d_timer,COIN_TOTAL_MS jne coin_test_fail cmp total,COIN_TOTAL_MS jb coin_test_fail mov eax,COIN_TOTAL_MS add eax,deltaTime3D cmp total,eax jae coin_test_fail mov eax,expected cmp bankroll,eax jne coin_test_fail call CoinSettle3D mov eax,expected cmp bankroll,eax jne coin_test_fail mov eax,seedSnapshot cmp rngSeed3D,eax jne coin_test_fail test iterations,1 jz @F cmp engineMode,MODE_WALK jne coin_test_fail @@: dec iterations jnz coin_test_round ; Exit during every animation phase settles the paid bet before leaving. mov coinTestStage3D,5 xor esi,esi coin_test_exit_phase: mov coin3d_state,COIN_TOSS mov coin3d_choice,1 mov coin3d_result,1 mov coin3d_bet,100 mov bankroll,99900 mov coinExitQueued3D,0 mov engineMode,MODE_COIN mov eax,coinTestTimes3D[esi*4] cmp eax,COIN_TOTAL_MS jb @F dec eax @@: mov coin3d_timer,eax mov mouseClick3D,1 mov mouseX3D,280 mov mouseY3D,9 mov deltaTime3D,16 call HandleCoinInput mov deltaTime3D,COIN_TOTAL_MS cmp engineMode,MODE_WALK je @F call HandleCoinInput @@: cmp engineMode,MODE_WALK jne coin_test_fail cmp bankroll,100100 jne coin_test_fail inc esi cmp esi,9 jb coin_test_exit_phase ; Capture the actual renderer; rendering cannot move the simulation/RNG. mov coinTestStage3D,6 mov engineMode,MODE_COIN mov coin3d_choice,1 mov coin3d_result,1 mov coinStartPhase3D,96 mov coin3d_win,200 mov coinExitQueued3D,0 mov eax,rngSeed3D mov seedSnapshot,eax xor esi,esi coin_test_snapshot: mov coin3d_state,COIN_TOSS test esi,esi jnz @F mov coin3d_state,COIN_IDLE @@: cmp esi,8 jne @F mov coin3d_state,COIN_RESULT @@: mov eax,coinTestTimes3D[esi*4] mov coin3d_timer,eax call RenderCoinGame mov eax,coinTestTimes3D[esi*4] cmp coin3d_timer,eax jne coin_test_fail cmp bankroll,100100 jne coin_test_fail mov eax,seedSnapshot cmp rngSeed3D,eax jne coin_test_fail invoke WriteActionSnapshot3D,coinTestPaths3D[esi*4] test eax,eax jz coin_test_fail inc esi cmp esi,9 jb coin_test_snapshot mov coin3d_result,2 mov coin3d_choice,2 call RenderCoinGame cmp coinFace3D,1 jne coin_test_fail invoke WriteActionSnapshot3D,OFFSET coinTest9 mov coin3d_choice,1 ; Coin position remains continuous across release, flight and bounces. mov coin3d_state,COIN_TOSS xor esi,esi invoke CoinPose3D,0 mov eax,coinX3D mov previousX,eax mov eax,coinY3D mov previousY,eax coin_test_pose: invoke CoinPose3D,esi mov eax,coinX3D sub eax,previousX test eax,eax jns @F neg eax @@: cmp eax,2 ja coin_test_fail mov eax,coinY3D sub eax,previousY test eax,eax jns @F neg eax @@: cmp eax,2 ja coin_test_fail mov eax,coinX3D mov previousX,eax mov eax,coinY3D mov previousY,eax cmp coinWidth3D,32 jb coin_test_fail cmp coinHeight3D,3 jb coin_test_fail inc esi cmp esi,COIN_TOTAL_MS jbe coin_test_pose mov coin3d_state,COIN_RESULT mov mouseClick3D,1 mov mouseX3D,250 mov mouseY3D,226 call HandleCoinInput cmp coin3d_state,COIN_IDLE jne coin_test_fail cmp bankroll,100100 jne coin_test_fail call HandleCoinInput cmp coin3d_state,COIN_IDLE jne coin_test_fail mov bankroll,999999999 mov coin3d_state,COIN_TOSS mov coin3d_bet,5000 mov coin3d_choice,1 mov coin3d_result,1 call CoinSettle3D call CoinSettle3D cmp bankroll,1000000000 jne coin_test_fail call CoinEscape3D cmp engineMode,MODE_WALK jne coin_test_fail mov eax,oldBank mov bankroll,eax mov eax,oldSeed mov rngSeed3D,eax mov eax,oldMode mov engineMode,eax mov eax,oldDelta mov deltaTime3D,eax call ClearKeys3D call RunCoinDetailRenderTest3D test eax,eax jz @F ret @@: call FreeNativeCoinArt3D xor eax,eax ret coin_test_fail: mov eax,coinTestStage3D add eax,8100 ret RunCoinTest3D ENDP