KAZIK/src_graphics/native_poker.inc
Artvasil09 3ad5bf4c9d Develop assembly-only casino scenes and native games
Add native Durak, poker, blackjack, roulette, Buckshot and billiards scenes with animation assets and regression tests. Improve arrival, city, hall, profiles, shops, audio and exit handling; remove the portable C game core and refresh shipping executables.
2026-10-08 22:39:19 +03:00

601 lines
13 KiB
PHP

; Heads-up no-limit Hold'em: real shuffled deck, four betting streets, no console.
InitNativePoker3D PROC
mov cardExitActive3D, 0
call LoadCardTableAssets3D
test eax, eax
jz @F
mov pkState3D, PK_IDLE
mov pkError3D, 0
mov pkPot3D, 0
mov pkAiMessage3D, 0
mov pkStreet3D, 0
mov pkBoardCount3D, 0
mov pkResult3D, 0
mov pkChipTimer3D, 320
call ClearKeys3D
mov eax, 1
@@:
ret
InitNativePoker3D ENDP
PokerPay3D PROC uses ebx actor:DWORD,amount:DWORD
mov ebx, actor
mov eax, amount
mov edx, bankroll
test ebx, ebx
jz @F
mov edx, pkStack3D
@@:
cmp eax, edx
jbe @F
mov eax, edx
@@:
test ebx, ebx
jnz poker_pay_dealer
sub bankroll, eax
jmp poker_pay_pot
poker_pay_dealer:
sub pkStack3D, eax
poker_pay_pot:
add pkPaid3D[ebx*4], eax
add pkPot3D, eax
mov pkChipAmount3D, eax
mov pkChipActor3D, ebx
mov pkChipTimer3D, 0
ret
PokerPay3D ENDP
StartNativePoker3D PROC uses ebx esi
cmp pkState3D, PK_IDLE
je @F
cmp pkState3D, PK_RESULT
jne poker_start_done
@@:
mov eax, bankroll
cmp eax, pkBlind3D
jb poker_start_empty
mov pkStack3D, eax
xor pkButton3D, 1
mov pkStreet3D, 0
mov pkPot3D, 0
mov pkPaid3D[0], 0
mov pkPaid3D[4], 0
mov pkActed3D[0], 0
mov pkActed3D[4], 0
mov pkRaisedCount3D, 0
mov pkCanRaise3D, 1
mov pkBoardCount3D, 0
mov pkOldBoardCount3D, 0
mov pkCursor3D, 4
mov pkResult3D, 0
mov pkError3D, 0
mov pkAiMessage3D, 0
mov eax, pkBlind3D
mov pkMinRaise3D, eax
mov pkRaise3D, eax
mov pkCurrent3D, eax
invoke ShuffleCards3D, OFFSET pkDeck3D
mov esi, pkButton3D
xor esi, 1
shl esi, 3 ; first card goes to the non-button player
mov ebx, esi
xor ebx, 8
mov eax, pkDeck3D[0]
mov pkHole3D[esi], eax
mov eax, pkDeck3D[4]
mov pkHole3D[ebx], eax
mov eax, pkDeck3D[8]
mov pkHole3D[esi+4], eax
mov eax, pkDeck3D[12]
mov pkHole3D[ebx+4], eax
mov ebx, pkButton3D
mov eax, pkBlind3D
shr eax, 1
invoke PokerPay3D, ebx, eax
xor ebx, 1
invoke PokerPay3D, ebx, pkBlind3D
mov eax, pkButton3D
mov pkTurn3D, eax
mov pkTimer3D, 0
mov pkState3D, PK_DEAL
call ClearKeys3D
invoke PlayCasinoSound3D, OFFSET soundCards, 0, 1
call SaveProgress3D
poker_start_done:
ret
poker_start_empty:
mov pkError3D, 1
ret
StartNativePoker3D ENDP
PokerNextTurn3D PROC actor:DWORD
mov eax, pkPaid3D[0]
cmp eax, pkPaid3D[4]
jne poker_switch_turn
cmp bankroll, 0
je poker_finish_street
cmp pkStack3D, 0
je poker_finish_street
cmp pkActed3D[0], 0
je poker_switch_turn
cmp pkActed3D[4], 0
jne poker_finish_street
poker_switch_turn:
mov eax, actor
xor eax, 1
mov pkTurn3D, eax
mov pkTimer3D, 0
mov pkState3D, PK_PLAYER
call ClearKeys3D
mov eax, pkTurn3D
test eax, eax
jz @F
mov pkState3D, PK_AI
@@:
ret
poker_finish_street:
call PokerNextStreet3D
ret
PokerNextTurn3D ENDP
PokerCall3D PROC uses ebx esi actor:DWORD
mov pkError3D, 0
mov ebx, actor
mov eax, pkCurrent3D
sub eax, pkPaid3D[ebx*4]
invoke PokerPay3D, ebx, eax
mov pkActed3D[ebx*4], 1
; Heads-up unmatched all-in excess is returned; no phantom side pot.
mov eax, pkPaid3D[ebx*4]
cmp eax, pkCurrent3D
jae poker_call_next
mov esi, ebx
xor esi, 1
mov edx, pkPaid3D[esi*4]
sub edx, eax
sub pkPot3D, edx
mov pkPaid3D[esi*4], eax
mov pkCurrent3D, eax
test esi, esi
jnz @F
add bankroll, edx
jmp poker_call_next
@@:
add pkStack3D, edx
poker_call_next:
invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1
invoke PokerNextTurn3D, ebx
ret
PokerCall3D ENDP
PokerRaise3D PROC uses ebx esi edi actor:DWORD,extra:DWORD
local owed:DWORD,available:DWORD
cmp pkCanRaise3D, 0
je poker_raise_done
mov ebx, actor
mov esi, ebx
xor esi, 1
mov eax, pkCurrent3D
sub eax, pkPaid3D[ebx*4]
mov owed, eax
mov eax, bankroll
test ebx, ebx
jz @F
mov eax, pkStack3D
@@:
mov available, eax
mov edi, extra
add edi, owed
cmp edi, eax
jbe @F
mov edi, eax
@@:
; Never ask the opponent to cover more than their effective stack.
mov eax, bankroll
test esi, esi
jz @F
mov eax, pkStack3D
@@:
add eax, pkPaid3D[esi*4]
sub eax, pkPaid3D[ebx*4]
cmp edi, eax
jbe @F
mov edi, eax
@@:
cmp edi, owed
jbe poker_raise_as_call
mov eax, edi
sub eax, owed
cmp eax, pkMinRaise3D
jae poker_full_raise
cmp edi, available
jne poker_raise_invalid
; A short all-in does not reopen raising for a player who already acted.
mov pkCanRaise3D, 0
jmp poker_commit_raise
poker_full_raise:
mov pkMinRaise3D, eax
mov pkRaise3D, eax
mov pkActed3D[esi*4], 0
mov pkCanRaise3D, 1
poker_commit_raise:
mov pkError3D, 0
invoke PokerPay3D, ebx, edi
mov eax, pkPaid3D[ebx*4]
mov pkCurrent3D, eax
mov pkActed3D[ebx*4], 1
inc pkRaisedCount3D
invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1
invoke PokerNextTurn3D, ebx
poker_raise_done:
ret
poker_raise_invalid:
cmp actor, 0
jne poker_raise_as_call
mov pkError3D, 2
ret
poker_raise_as_call:
cmp actor, 1
jne @F
mov pkAiMessage3D, 1
cmp owed, 0
je @F
mov pkAiMessage3D, 2
@@:
invoke PokerCall3D, ebx
ret
PokerRaise3D ENDP
PokerFold3D PROC actor:DWORD
cmp pkState3D, PK_RESULT
je poker_fold_done
mov pkResult3D, 0
mov pkOutcome3D, 1
cmp actor, 0
je poker_fold_player
mov eax, pkPot3D
add bankroll, eax
mov pkOutcome3D, 0
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
jmp poker_fold_settled
poker_fold_player:
mov eax, pkPot3D
add pkStack3D, eax
invoke PlayCasinoSound3D, OFFSET soundRoundLose, 0, 1
poker_fold_settled:
mov pkState3D, PK_RESULT
call ClearKeys3D
call SaveProgress3D
poker_fold_done:
ret
PokerFold3D ENDP
PokerNextStreet3D PROC uses ebx esi
cmp pkStreet3D, 3
je poker_begin_reveal
inc pkStreet3D
mov eax, pkBoardCount3D
mov pkOldBoardCount3D, eax
mov eax, pkStreet3D
add eax, 2
mov pkBoardCount3D, eax
inc pkCursor3D ; burn one card before each board street
mov esi, pkOldBoardCount3D
poker_deal_board:
mov ebx, pkCursor3D
mov eax, pkDeck3D[ebx*4]
mov pkBoard3D[esi*4], eax
inc pkCursor3D
inc esi
cmp esi, pkBoardCount3D
jb poker_deal_board
mov pkPaid3D[0], 0
mov pkPaid3D[4], 0
mov pkActed3D[0], 0
mov pkActed3D[4], 0
mov pkCurrent3D, 0
mov pkRaisedCount3D, 0
mov pkCanRaise3D, 1
mov eax, pkBlind3D
mov pkMinRaise3D, eax
mov pkRaise3D, eax
mov eax, pkButton3D
xor eax, 1
mov pkTurn3D, eax
mov pkTimer3D, 0
mov pkState3D, PK_BOARD
invoke PlayCasinoSound3D, OFFSET soundCards, 0, 1
ret
poker_begin_reveal:
mov pkTimer3D, 0
mov pkState3D, PK_REVEAL
ret
PokerNextStreet3D ENDP
PokerShowdown3D PROC uses ebx esi edi
cmp pkState3D, PK_RESULT
je poker_showdown_done
xor ebx, ebx
poker_evaluate_player:
lea edi, pkEvalHand3D
lea esi, pkHole3D[ebx*8]
movsd
movsd
lea esi, pkBoard3D
mov ecx, 5
rep movsd
invoke EvaluateNativePoker3D, OFFSET pkEvalHand3D, 7
mov pkScore3D[ebx*4], eax
inc ebx
cmp ebx, 2
jb poker_evaluate_player
mov pkResult3D, 1
mov eax, pkScore3D[0]
cmp eax, pkScore3D[4]
ja poker_showdown_lose
je poker_showdown_tie
mov eax, pkPot3D
add bankroll, eax
mov pkOutcome3D, 0
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
jmp poker_showdown_settled
poker_showdown_lose:
mov eax, pkPot3D
add pkStack3D, eax
mov pkOutcome3D, 1
invoke PlayCasinoSound3D, OFFSET soundRoundLose, 0, 1
jmp poker_showdown_settled
poker_showdown_tie:
mov eax, pkPot3D
shr eax, 1
mov edx, pkPot3D
and edx, 1
cmp pkButton3D, 1
jne @F
add eax, edx ; odd chip goes to the non-button player
@@:
add bankroll, eax
mov edx, pkPot3D
sub edx, eax
add pkStack3D, edx
mov pkOutcome3D, 2
poker_showdown_settled:
mov pkState3D, PK_RESULT
call ClearKeys3D
call SaveProgress3D
poker_showdown_done:
ret
PokerShowdown3D ENDP
; The AI sees only its two cards and the already exposed board. No player cards/future deck.
PokerAIDecide3D PROC uses ebx esi edi
local strength:DWORD,owed:DWORD
mov eax, pkCurrent3D
sub eax, pkPaid3D[4]
mov owed, eax
cmp pkBoardCount3D, 3
jae poker_ai_postflop
mov eax, pkHole3D[8]
xor edx, edx
mov ecx, 13
div ecx
mov esi, edx
mov eax, pkHole3D[12]
xor edx, edx
div ecx
mov strength, 0
cmp esi, edx
je poker_ai_pair
cmp esi, 8
jb @F
inc strength
@@:
cmp edx, 8
jb poker_ai_odds
inc strength
jmp poker_ai_odds
poker_ai_pair:
mov strength, 3
cmp esi, 7
jb poker_ai_odds
mov strength, 5
jmp poker_ai_odds
poker_ai_postflop:
lea edi, pkEvalHand3D
lea esi, pkHole3D[8]
movsd
movsd
lea esi, pkBoard3D
mov ecx, pkBoardCount3D
rep movsd
mov eax, pkBoardCount3D
add eax, 2
invoke EvaluateNativePoker3D, OFFSET pkEvalHand3D, eax
invoke NativePokerClass3D, eax
inc eax
mov strength, eax
poker_ai_odds:
invoke RandomRange3D, 100
mov ebx, eax
cmp owed, 0
je poker_ai_consider_raise
mov eax, pkBlind3D
imul eax, 2
cmp owed, eax
jbe poker_ai_small_call
cmp strength, 3
jae poker_ai_consider_raise
cmp ebx, 18
jb poker_ai_call
jmp poker_ai_fold
poker_ai_small_call:
cmp strength, 1
jae poker_ai_consider_raise
cmp ebx, 32
jb poker_ai_fold
poker_ai_consider_raise:
cmp pkCanRaise3D, 0
je poker_ai_call
cmp pkRaisedCount3D, 2
jae poker_ai_call
cmp bankroll, 0
je poker_ai_call
cmp strength, 3
jae poker_ai_strong_raise
cmp ebx, 9
jae poker_ai_call
jmp poker_ai_raise
poker_ai_strong_raise:
cmp ebx, 62
jae poker_ai_call
poker_ai_raise:
mov pkAiMessage3D, 3
invoke PokerRaise3D, 1, pkMinRaise3D
ret
poker_ai_fold:
mov pkAiMessage3D, 4
invoke PokerFold3D, 1
ret
poker_ai_call:
mov pkAiMessage3D, 1
cmp owed, 0
je @F
mov pkAiMessage3D, 2
@@:
invoke PokerCall3D, 1
ret
PokerAIDecide3D ENDP
HandleNativePoker3D PROC uses ebx
call HandleCardExit3D
test eax, eax
jnz poker_input_done
invoke CardTableMouse3D, MODE_POKER
cmp cardExitActive3D, 0
jne poker_input_done
cmp engineMode, MODE_POKER
jne poker_input_done
cmp pkChipTimer3D, 320
jae @F
mov eax, deltaTime3D
add pkChipTimer3D, eax
@@:
cmp pkState3D, PK_IDLE
je poker_ready_input
cmp pkState3D, PK_RESULT
je poker_ready_input
cmp pkState3D, PK_PLAYER
je poker_player_input
mov eax, deltaTime3D
add pkTimer3D, eax
cmp pkState3D, PK_AI
jne poker_animate_deal
cmp pkTimer3D, 650
jb poker_input_done
call PokerAIDecide3D
ret
poker_animate_deal:
cmp pkState3D, PK_REVEAL
jne @F
cmp pkTimer3D, 650
jb poker_input_done
call PokerShowdown3D
ret
@@:
mov eax, TABLE_FLIGHT_MS*4
cmp pkState3D, PK_DEAL
je poker_animation_limit
mov eax, pkBoardCount3D
sub eax, pkOldBoardCount3D
imul eax, TABLE_FLIGHT_MS
poker_animation_limit:
cmp pkTimer3D, eax
jb poker_input_done
mov pkTimer3D, 0
cmp pkState3D, PK_BOARD
jne poker_begin_turn
cmp bankroll, 0
je poker_runout
cmp pkStack3D, 0
je poker_runout
poker_begin_turn:
mov pkState3D, PK_PLAYER
call ClearKeys3D
cmp pkTurn3D, 0
je poker_input_done
mov pkState3D, PK_AI
ret
poker_runout:
call PokerNextStreet3D
ret
poker_ready_input:
invoke Pressed3D, 26h
test eax, eax
jz @F
cmp pkBlind3D, 1000
jae @F
add pkBlind3D, 50
@@:
invoke Pressed3D, 28h
test eax, eax
jz @F
cmp pkBlind3D, 50
jbe @F
sub pkBlind3D, 50
@@:
invoke Pressed3D, 20h
test eax, eax
jz poker_input_done
call StartNativePoker3D
ret
poker_player_input:
invoke Pressed3D, 41h
test eax, eax
jz @F
invoke PokerRaise3D, 0, bankroll
ret
@@:
invoke Pressed3D, 26h
test eax, eax
jz @F
cmp pkRaise3D, 50000
jae @F
mov eax, pkBlind3D
add pkRaise3D, eax
@@:
invoke Pressed3D, 28h
test eax, eax
jz @F
mov eax, pkMinRaise3D
cmp pkRaise3D, eax
jbe @F
mov eax, pkBlind3D
sub pkRaise3D, eax
mov eax, pkMinRaise3D
cmp pkRaise3D, eax
jae @F
mov pkRaise3D, eax
@@:
invoke Pressed3D, 46h
test eax, eax
jz @F
invoke PokerFold3D, 0
ret
@@:
invoke Pressed3D, 52h
test eax, eax
jz @F
invoke PokerRaise3D, 0, pkRaise3D
ret
@@:
invoke Pressed3D, 43h
test eax, eax
jnz poker_player_call
invoke Pressed3D, 20h
test eax, eax
jz poker_input_done
poker_player_call:
invoke PokerCall3D, 0
poker_input_done:
ret
HandleNativePoker3D ENDP