; 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 TriggerCharmLossProtection, pkPaid3D[0] test eax, eax jnz poker_fold_settled 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 TriggerCharmLossProtection, pkPaid3D[0] test eax, eax jnz poker_showdown_settled 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 invoke PokerBotAct3D,1 ret PokerAIDecide3D ENDP PokerBotAct3D PROC uses ebx esi edi actor:DWORD local strength:DWORD,owed:DWORD mov eax, pkCurrent3D mov ecx,actor sub eax, pkPaid3D[ecx*4] mov owed, eax cmp pkBoardCount3D, 3 jae poker_ai_postflop mov ebx,actor shl ebx,3 mov eax, pkHole3D[ebx] xor edx, edx mov ecx, 13 div ecx mov esi, edx mov eax, pkHole3D[ebx+4] 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 mov eax,actor lea esi, pkHole3D[eax*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 mov eax,bankroll cmp actor,1 je @F mov eax,pkStack3D @@: cmp eax, 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, actor, pkMinRaise3D ret poker_ai_fold: mov pkAiMessage3D, 4 invoke PokerFold3D, actor ret poker_ai_call: mov pkAiMessage3D, 1 cmp owed, 0 je @F mov pkAiMessage3D, 2 @@: invoke PokerCall3D, actor ret PokerBotAct3D 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 @@: cmp tournamentMode, 1 jne poker_regular_start cmp pkState3D, PK_RESULT jne poker_regular_start invoke Pressed3D, 20h test eax, eax jnz poker_tourney_report invoke Pressed3D, 0Dh test eax, eax jnz poker_tourney_report ret poker_tourney_report: cmp pkOutcome3D, 1 je poker_tourney_loss invoke TowerReportRoundOutcome, 1 ret poker_tourney_loss: invoke TowerReportRoundOutcome, 2 ret poker_regular_start: 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