; Headless verification executes the production MASM handlers and framebuffer renderer. wsprintfA PROTO C :DWORD,:DWORD,:VARARG .data tableVectorPath db "build\tables\poker-vectors.bin",0 tableVectorCount dd 0 tableDuplicate dd 0,0,2,3,4 tableAces dd 12,25,38,9 tablePKDeal db "build\actions\poker-deal.bmp",0 tablePKFlop db "build\actions\poker-flop.bmp",0 tablePKTurn db "build\actions\poker-turn.bmp",0 tablePKReveal db "build\actions\poker-reveal.bmp",0 tablePKResult db "build\actions\poker-result.bmp",0 tableBJDeal db "build\actions\blackjack-deal.bmp",0 tableBJHit db "build\actions\blackjack-hit.bmp",0 tableBJResult db "build\actions\blackjack-result.bmp",0 tableHandSnapshotFormat db "build\actions\poker-hand-%02u.bmp",0 tableHandSnapshotName db 128 dup(0) .code RunCardTablesTest3D PROC uses ebx esi edi local countRead:DWORD,vectors:DWORD,heap:DWORD,rounds:DWORD,ticks:DWORD,seenLo:DWORD,seenHi:DWORD local savedBank:DWORD,savedSeed:DWORD,savedState:DWORD,savedPot:DWORD,savedStack:DWORD,savedPaid:DWORD call LoadArrivalAssets3D cmp handsPack3D.frames, 8 jne table_fail_20 call LoadCardTableAssets3D test eax, eax jz table_fail_20 cmp cardTablePixels3D, 0 je table_fail_20 mov interactTargetId, INTERACT_POKER call Trigger3DInteraction cmp engineMode, MODE_POKER jne table_fail_20 mov interactTargetId, INTERACT_BLACKJACK call Trigger3DInteraction cmp engineMode, MODE_BLACKJACK jne table_fail_20 invoke CreateFileA, OFFSET tableVectorPath, 80000000h, 1, 0, 3, 80h, 0 cmp eax, -1 je table_fail_20 mov ebx, eax invoke ReadFile, ebx, OFFSET tableVectorCount, 4, ADDR countRead, 0 cmp countRead, 4 jne table_fail_20 cmp tableVectorCount, 9021 jne table_fail_20 invoke GetProcessHeap mov heap, eax invoke HeapAlloc, eax, 0, 9021 * 36 mov vectors, eax test eax, eax jz table_fail_20 invoke ReadFile, ebx, vectors, 9021 * 36, ADDR countRead, 0 invoke CloseHandle, ebx cmp countRead, 9021 * 36 jne table_fail_20 mov esi, vectors mov edi, tableVectorCount table_vectors: lea eax, [esi+4] invoke EvaluateNativePoker3D, eax, DWORD PTR [esi] cmp eax, [esi+32] jne table_fail_21 add esi, 36 dec edi jnz table_vectors invoke HeapFree, heap, 0, vectors invoke EvaluateNativePoker3D, OFFSET tableDuplicate, 5 cmp eax, 7463 jne table_fail_21 invoke NativeBJScore3D, OFFSET tableAces, 4 cmp eax, 13 jne table_fail_22 ; Blinds and the big blind's option; postflop action starts off-button. mov engineMode, MODE_POKER mov pkButton3D, 1 mov pkBlind3D, 50 mov bankroll, 1000 mov pkState3D, PK_IDLE call StartNativePoker3D cmp pkPot3D, 75 jne table_fail_23 cmp pkTurn3D, 0 jne table_fail_23 cmp pkPaid3D, 25 jne table_fail_23 mov eax, pkDeck3D cmp pkHole3D[8], eax jne table_fail_23 invoke PokerRaise3D, 0, 10 cmp pkError3D, 2 jne table_fail_23 cmp pkPot3D, 75 jne table_fail_23 cmp bankroll, 975 jne table_fail_23 invoke PokerCall3D, 0 cmp pkState3D, PK_AI jne table_fail_23 invoke PokerCall3D, 1 cmp pkState3D, PK_BOARD jne table_fail_23 cmp pkBoardCount3D, 3 jne table_fail_23 cmp pkTurn3D, 1 jne table_fail_23 cmp pkCursor3D, 8 jne table_fail_23 ; A shared royal flush must split, including the correct odd chip. mov pkBoard3D[0], 8 mov pkBoard3D[4], 9 mov pkBoard3D[8], 10 mov pkBoard3D[12], 11 mov pkBoard3D[16], 12 mov pkBoardCount3D, 5 mov pkHole3D[0], 0 mov pkHole3D[4], 1 mov pkHole3D[8], 13 mov pkHole3D[12], 14 mov pkButton3D, 0 mov pkPot3D, 151 mov bankroll, 1000 mov pkStack3D, 1000 mov pkState3D, PK_REVEAL call PokerShowdown3D cmp pkOutcome3D, 2 jne table_fail_24 cmp bankroll, 1075 jne table_fail_24 cmp pkStack3D, 1076 jne table_fail_24 call PokerShowdown3D cmp bankroll, 1075 jne table_fail_24 call RenderNativePoker3D invoke WriteActionSnapshot3D, OFFSET tablePKResult ; Unmatched short all-in money goes back to its owner. mov pkPaid3D, 100 mov pkPaid3D[4], 400 mov pkCurrent3D, 400 mov pkPot3D, 500 mov pkStack3D, 600 mov bankroll, 50 mov pkState3D, PK_PLAYER mov pkStreet3D, 0 mov pkCursor3D, 4 mov pkBoardCount3D, 0 invoke PokerCall3D, 0 cmp pkPot3D, 300 jne table_fail_24 cmp pkStack3D, 850 jne table_fail_24 ; Effective-stack all-in must run out the whole board without user input. mov bankroll, 1000 mov pkState3D, PK_IDLE mov pkButton3D, 1 call StartNativePoker3D invoke PokerRaise3D, 0, bankroll cmp bankroll, 0 jne table_fail_24 invoke PokerCall3D, 1 mov ticks, 0 mov deltaTime3D, 50 table_all_in_tick: call HandleNativePoker3D cmp pkState3D, PK_RESULT je table_all_in_settled inc ticks cmp ticks, 200 jae table_fail_30 jmp table_all_in_tick table_all_in_settled: cmp pkBoardCount3D, 5 jne table_fail_24 mov eax, bankroll add eax, pkStack3D cmp eax, 2000 jne table_fail_24 ; Insufficient funds cannot start a hand. A one-blind bankroll still completes. mov pkState3D, PK_IDLE mov bankroll, 49 call StartNativePoker3D cmp pkState3D, PK_IDLE jne table_fail_24 cmp bankroll, 49 jne table_fail_24 mov pkButton3D, 0 mov bankroll, 50 call StartNativePoker3D cmp pkTurn3D, 1 jne table_fail_24 invoke PokerCall3D, 1 mov ticks, 0 table_low_bank_tick: call HandleNativePoker3D cmp pkState3D, PK_RESULT je table_low_bank_settled inc ticks cmp ticks, 200 jae table_fail_30 jmp table_low_bank_tick table_low_bank_settled: mov eax, bankroll add eax, pkStack3D cmp eax, 100 jne table_fail_24 ; State, bank and RNG cannot change when the same frame is drawn repeatedly. mov bankroll, 10000 mov pkState3D, PK_IDLE call StartNativePoker3D mov pkState3D, PK_DEAL mov pkTimer3D, 310 mov eax, bankroll mov savedBank, eax mov eax, rngSeed3D mov savedSeed, eax mov eax, pkPot3D mov savedPot, eax mov edi, 30 table_render_repeat: call RenderNativePoker3D dec edi jnz table_render_repeat mov eax, savedBank cmp bankroll, eax jne table_fail_25 mov eax, savedSeed cmp rngSeed3D, eax jne table_fail_25 mov eax, savedPot cmp pkPot3D, eax jne table_fail_25 cmp pkState3D, PK_DEAL jne table_fail_25 invoke WriteActionSnapshot3D, OFFSET tablePKDeal xor edi, edi table_hand_sequence: mov eax, edi imul eax, 60 mov pkTimer3D, eax call RenderNativePoker3D invoke wsprintfA, OFFSET tableHandSnapshotName, OFFSET tableHandSnapshotFormat, edi invoke WriteActionSnapshot3D, OFFSET tableHandSnapshotName inc edi cmp edi, 24 jb table_hand_sequence mov pkState3D, PK_BOARD mov pkStreet3D, 1 mov pkBoard3D[0], 8 mov pkBoard3D[4], 24 mov pkBoard3D[8], 35 mov pkOldBoardCount3D, 0 mov pkBoardCount3D, 3 mov pkTimer3D, 400 call RenderNativePoker3D invoke WriteActionSnapshot3D, OFFSET tablePKFlop mov pkState3D, PK_PLAYER mov pkChipTimer3D, 320 call RenderNativePoker3D invoke WriteActionSnapshot3D, OFFSET tablePKTurn mov pkState3D, PK_REVEAL mov pkTimer3D, 90 call RenderNativePoker3D invoke WriteActionSnapshot3D, OFFSET tablePKReveal ; Client pixels convert to logical coordinates even with pillarboxing. mov viewWidth3D, 800 mov viewHeight3D, 600 mov viewLeft3D, 100 mov viewTop3D, 0 invoke WindowEvents3D, 0, 201h, 0, 023F01A9h ; (425,575) -> (130,230) cmp mouseClick3D, 1 jne table_fail_26 cmp mouseX3D, 130 jne table_fail_26 cmp mouseY3D, 230 jne table_fail_26 mov mouseClick3D, 0 invoke WindowEvents3D, 0, 201h, 0, 023F0032h ; click in the black left bar cmp mouseClick3D, 0 jne table_fail_26 ; Mouse and keyboard share the command path; animated states ignore clicks. call ClearKeys3D mov mouseClick3D, 1 mov mouseX3D, 100 mov mouseY3D, 230 mov pkState3D, PK_PLAYER invoke CardTableMouse3D, MODE_POKER cmp pressedKeys3D[52h], 1 jne table_fail_26 call ClearKeys3D mov mouseClick3D, 1 mov pkState3D, PK_AI invoke CardTableMouse3D, MODE_POKER cmp pressedKeys3D[52h], 0 jne table_fail_26 mov engineMode, MODE_WALK mov dice3d_state, 1 call TableBusy3D test eax, eax jnz table_fail_26 mov engineMode, MODE_POKER call TableBusy3D cmp eax, 1 jne table_fail_26 ; The AI's decision cannot depend on the unseen player cards or undealt cards. mov pkHole3D[8], 12 mov pkHole3D[12], 25 mov pkBoardCount3D, 0 mov pkStreet3D, 0 mov pkState3D, PK_AI mov pkPaid3D, 200 mov pkPaid3D[4], 50 mov pkCurrent3D, 200 mov pkPot3D, 250 mov bankroll, 9800 mov pkStack3D, 9950 mov pkMinRaise3D, 150 mov pkRaisedCount3D, 0 mov pkCanRaise3D, 1 mov rngSeed3D, 77123 call PokerAIDecide3D mov eax, bankroll mov savedBank, eax mov eax, pkStack3D mov savedStack, eax mov eax, pkPot3D mov savedPot, eax mov eax, pkState3D mov savedState, eax mov eax, pkPaid3D[4] mov savedPaid, eax mov pkHole3D, 2 mov pkHole3D[4], 3 mov pkDeck3D[180], 51 mov pkState3D, PK_AI mov pkPaid3D, 200 mov pkPaid3D[4], 50 mov pkCurrent3D, 200 mov pkPot3D, 250 mov bankroll, 9800 mov pkStack3D, 9950 mov pkMinRaise3D, 150 mov pkRaisedCount3D, 0 mov pkCanRaise3D, 1 mov rngSeed3D, 77123 call PokerAIDecide3D mov eax, savedBank cmp bankroll, eax jne table_fail_27 mov eax, savedStack cmp pkStack3D, eax jne table_fail_27 mov eax, savedPot cmp pkPot3D, eax jne table_fail_27 mov eax, savedState cmp pkState3D, eax jne table_fail_27 mov eax, savedPaid cmp pkPaid3D[4], eax jne table_fail_27 mov rounds, 500 mov deltaTime3D, 50 table_poker_round: mov eax, rounds imul eax, 137 mov rngSeed3D, eax mov bankroll, 10000 mov pkState3D, PK_IDLE call StartNativePoker3D mov seenLo, 0 mov seenHi, 0 xor esi, esi table_check_deck: mov eax, pkDeck3D[esi*4] cmp eax, 52 jae table_fail_28 cmp eax, 32 jb @F sub eax, 32 bts seenHi, eax jc table_fail_28 jmp table_next_deck @@: bts seenLo, eax jc table_fail_28 table_next_deck: inc esi cmp esi, 52 jb table_check_deck mov ticks, 0 table_poker_tick: cmp pkState3D, PK_RESULT je table_poker_settled mov eax, bankroll add eax, pkStack3D add eax, pkPot3D cmp eax, 20000 jne table_fail_29 cmp pkState3D, PK_PLAYER jne table_poker_handle mov eax, ticks and eax, 7 cmp eax, 1 je table_poker_raise cmp eax, 3 jne table_poker_call invoke PokerFold3D, 0 jmp table_poker_handle table_poker_raise: invoke PokerRaise3D, 0, pkMinRaise3D jmp table_poker_handle table_poker_call: invoke PokerCall3D, 0 table_poker_handle: call ClearKeys3D call HandleNativePoker3D inc ticks cmp ticks, 3000 jae table_fail_30 jmp table_poker_tick table_poker_settled: mov eax, bankroll add eax, pkStack3D cmp eax, 20000 jne table_fail_29 dec rounds jnz table_poker_round ; Natural, push and loss settle once, including the stake already deducted. mov engineMode, MODE_BLACKJACK mov cbStake3D, 100 mov cbBet3D, 100 mov bankroll, 99 mov cbState3D, CB_IDLE call StartNativeBlackjack3D cmp cbState3D, CB_IDLE jne table_fail_31 cmp bankroll, 99 jne table_fail_31 mov bankroll, 900 mov cbState3D, CB_PLAYER invoke NativeBJSettle3D, 3 cmp bankroll, 1150 jne table_fail_31 invoke NativeBJSettle3D, 3 cmp bankroll, 1150 jne table_fail_31 mov cbState3D, CB_PLAYER mov bankroll, 900 invoke NativeBJSettle3D, 2 cmp bankroll, 1000 jne table_fail_31 mov rounds, 500 mov cbBet3D, 100 table_bj_round: mov eax, rounds imul eax, 161 mov rngSeed3D, eax mov bankroll, 10000 mov cbState3D, CB_IDLE call StartNativeBlackjack3D mov ticks, 0 table_bj_tick: cmp cbState3D, CB_RESULT je table_bj_settled cmp cbState3D, CB_PLAYER jne table_bj_handle mov pressedKeys3D[53h], 1 cmp cbPlayerScore3D, 16 jae @F mov pressedKeys3D[53h], 0 mov pressedKeys3D[48h], 1 @@: cmp cbPlayerCount3D, 2 jne table_bj_handle test rounds, 1 jz table_bj_handle mov pressedKeys3D[44h], 1 table_bj_handle: call HandleNativeBlackjack3D call ClearKeys3D inc ticks cmp ticks, 3000 jae table_fail_32 jmp table_bj_tick table_bj_settled: mov eax, 10000 sub eax, cbStake3D cmp cbOutcome3D, 1 je table_bj_expected add eax, cbStake3D cmp cbOutcome3D, 2 je table_bj_expected add eax, cbStake3D cmp cbOutcome3D, 3 jne table_bj_expected mov edx, cbStake3D shr edx, 1 add eax, edx table_bj_expected: cmp eax, bankroll jne table_fail_33 cmp cbCursor3D, 26 ja table_fail_33 dec rounds jnz table_bj_round call RenderNativeBlackjack3D invoke WriteActionSnapshot3D, OFFSET tableBJResult mov cbState3D, CB_IDLE mov bankroll, 10000 call StartNativeBlackjack3D mov cbTimer3D, 600 call RenderNativeBlackjack3D invoke WriteActionSnapshot3D, OFFSET tableBJDeal mov cbState3D, CB_PLAYER call NativeBJHit3D mov cbTimer3D, 90 mov eax, rngSeed3D mov savedSeed, eax mov eax, bankroll mov savedBank, eax call RenderNativeBlackjack3D invoke WriteActionSnapshot3D, OFFSET tableBJHit mov eax, savedSeed cmp rngSeed3D, eax jne table_fail_25 mov eax, savedBank cmp bankroll, eax jne table_fail_25 call RunBJPartyTest3D test eax,eax jnz table_bj_party_failed call FreeCardTableAssets3D xor eax, eax ret table_bj_party_failed: ret table_fail_20: mov eax, 20 ret table_fail_21: mov eax, 21 ret table_fail_22: mov eax, 22 ret table_fail_23: mov eax, 23 ret table_fail_24: mov eax, 24 ret table_fail_25: mov eax, 25 ret table_fail_26: mov eax, 26 ret table_fail_27: mov eax, 27 ret table_fail_28: mov eax, 28 ret table_fail_29: mov eax, 29 ret table_fail_30: mov eax, 30 ret table_fail_31: mov eax, 31 ret table_fail_32: mov eax, 32 ret table_fail_33: mov eax, 33 ret RunCardTablesTest3D ENDP include tools\tests\blackjack_party_test.inc