Implement 32x32 BFS visitor navigation and daily contracts system with companion .npc journals; add native assembly scenes for Clover slots, Pyramid cards, Blackjack Party and Russian Party; package animation and sprite packs; add comprehensive offline test suites and rebuild shipping binaries.
609 lines
13 KiB
PHP
609 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
|
|
xor eax,eax
|
|
cmp pkOutcome3D,0
|
|
sete al
|
|
invoke NpcRecordRound3D,2,eax
|
|
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
|
|
xor eax,eax
|
|
cmp pkOutcome3D,0
|
|
sete al
|
|
invoke NpcRecordRound3D,2,eax
|
|
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
|