Skip to content
[OPEN_POKER]

Advanced Poker Bot Architecture: Equity और Testing

JJoão Carvalho||11 min read

एक advanced poker bot भरोसेमंद event loop को measurable decision system में बदलता है। Upgrade का मतलब सिर्फ “AI जोड़ना” नहीं है। इसका मतलब immutable decision snapshots, explicit poker features, range-aware equity, replay किए जा सकने वाले hands और ऐसा experiment loop है जो साबित कर सके कि policy बदली है। Basic bot का legal-action guard बनाए रखें। सारी smart functionality उसके पीछे रहती है।

Poker bot architecture series: 3 भागों में से भाग 2। अगर आपका runtime अब भी actions reject करता है तो Basic Poker Bot Architecture से शुरू करें। आगे Pro Poker Bot Architecture पढ़ें। Operating options की तुलना Poker Bot Cost in 2026 में करें।

Advanced poker bot architecture में क्या बदलता है?

एक advanced poker bot facts, estimates, policy और execution को अलग करता है। Facts latest server turn से आते हैं: pot, board, stacks, legal actions, hand ID और token। Estimates में equity और opponent range शामिल हैं। Policy दोनों का इस्तेमाल करके intent लौटाती है। Execution उस intent को आखिरी बार facts के against check करता है।

यह फर्क जरूरी है क्योंकि estimates गलत हो सकते हैं। Opponent model जरूरत से ज्यादा tight range assign कर सकता है। Monte Carlo run में sampling error हो सकता है। इन दोनों में से कोई error invalid raise या expired turn का response पैदा नहीं करना चाहिए। Inner policy probabilistic हो सकती है, लेकिन outer shell deterministic रहता है।

Data classExampleConfidenceOwner
Server factpot = 180, raise max 1,640AuthoritativeProtocol adapter
Derived factpot odds, effective stack, positionInputs सही हों तो exactFeature layer
Estimate43% showdown equitySampled या modeledEquity service
Beliefopponent button से 31% open करता हैUncertainOpponent model
Intentequity price से ऊपर होने के कारण callPolicy outputStrategy

इन्हें कभी एक untyped dictionary में flatten न करें। Confidence और ownership गायब होते ही guessed range server के raise bound जितनी भरोसेमंद दिखने लगती है।

Immutable decision snapshots कैसे काम करने चाहिए?

Immutable decision snapshot एक your_turn से capture किया गया complete, read-only input है। Equity या model work चलने के दौरान यह late network events को data बदलने से रोकता है। Tests में replay होने वाली unit भी यही बनती है।

from dataclasses import dataclass
from typing import Literal
 
Action = Literal["fold", "check", "call", "raise", "all_in"]
 
 
@dataclass(frozen=True)
class DecisionSnapshot:
    hand_id: str
    turn_token: str
    street: str
    hole: tuple[str, str]
    board: tuple[str, ...]
    pot: float
    stack: float
    to_call: float
    opponents: int
    position: str
    legal: tuple[Action, ...]
    min_raise: float | None
    max_raise: float | None
 
    @property
    def pot_odds(self) -> float:
        return self.to_call / (self.pot + self.to_call) if self.to_call else 0.0
 
    @property
    def stack_to_pot(self) -> float:
        return self.stack / self.pot if self.pot else float("inf")

Turn आते ही snapshot synchronously बनाएँ। फिर उसे async decision task को pass करें। Result भेजने से पहले उसके hand_id और turn_token की active turn से दोबारा तुलना करें। Open Poker tokens action के बाद consume हो जाते हैं और हर नया your_turn पिछले token को invalidate करता है, इसलिए stale work को discard करें, retry नहीं।

Message types reference wire fields document करता है। Reconnect के बाद आपका normalizer table_state भी accept करे, क्योंकि उसके player-specific hero section में hole cards और current legal actions होते हैं।

Equity और pot odds मिलकर decision कैसे बनाते हैं?

Equity बताती है कि assumed range के against showdown पर hand कितनी बार pot पाता है; pot odds call के लिए जरूरी break-even share बताती हैं। Future betting, range error और tournament objectives के adjustments से पहले, estimated equity call / (pot + call) से ज्यादा हो तो calling की chip expectation positive होती है।

अगर pot 180 है और call की cost 60 है, तो pot odds 60 / 240 = 25% हैं। 38% equity estimate उस raw threshold को 13 percentage points से clear करता है। हर एक-point edge पर call न करें। Monte Carlo variance, inaccurate opponent range और future action पतले margin को मिटा सकते हैं। हम explicit safety margin इस्तेमाल करते हैं और उसे log करते हैं।

from dataclasses import dataclass
 
 
@dataclass(frozen=True)
class EquityResult:
    equity: float
    trials: int
    range_name: str
 
 
def call_has_margin(snapshot: DecisionSnapshot, result: EquityResult,
                    margin: float = 0.03) -> bool:
    return (
        "call" in snapshot.legal
        and result.equity >= snapshot.pot_odds + margin
    )

Monte Carlo equity calculator Python implementation दिखाता है। Maintained evaluation primitives के लिए, strategy project के बीच खुद hand ranker लिखने के बजाय PokerKit's evaluator documentation बेहतर starting point है।

Opponent model को uncertainty कैसे represent करनी चाहिए?

Opponent model को “aggressive” या “fish” जैसे labels के बजाय counts और smoothed rates store करने चाहिए। शुरुआती useful features में voluntary preflop participation, preflop raise rate, three-bet opportunities और actions, postflop aggression, fold-to-bet opportunities और observed showdown hands शामिल हैं। हर rate के लिए denominator जरूरी है।

चार opportunities में दो बार raise करने वाले player की observed rate 50% है, लेकिन certainty लगभग नहीं है। Bayesian smoothing छोटे samples को policy झुलाने से रोकती है। Beta prior के साथ rate को (successes + alpha) / (opportunities + alpha + beta) से estimate किया जा सकता है। Neutral Beta(2, 2) prior चार chances में दो raises को 4 / 8 = 50% बनाता है, जबकि एक chance में zero raises 2 / 5 = 40% बनता है, confident zero नहीं।

Statistics को strategy बदलने वाली situations के हिसाब से segment करें। Position और street मायने रखते हैं। Table-wide “aggression” under-the-gun open और river check-raise को एक साथ मिला देता है। पचास sparse cells के बजाय कुछ ऐसे buckets से शुरू करें जिन्हें आप भर सकें। हमारी opponent modeling guide decay, showdown evidence और exploit caps पर विस्तार से जाती है।

एक baseline policy रखें जो opponent features को ignore करती हो। इसके बिना यह पता नहीं चलेगा कि adaptation ने मदद की या पूरा bot केवल एक हफ्ते तक run good कर गया।

Advanced policy interface को क्या return करना चाहिए?

Advanced policy को action intent, amount intent, reason codes, feature values और model metadata return करना चाहिए। केवल "call" जैसी plain string analysis के लिए बहुत छोटी है। Free-form essay code के लिए बहुत loose है। Typed record इस्तेमाल करें।

from dataclasses import dataclass, field
 
 
@dataclass(frozen=True)
class DecisionIntent:
    action: Action
    amount: float | None
    reason_code: str
    confidence: float
    features: dict[str, float] = field(default_factory=dict)
    policy_version: str = "range-equity-v3"
 
 
def decide(snapshot: DecisionSnapshot, eq: EquityResult) -> DecisionIntent:
    features = {
        "equity": eq.equity,
        "pot_odds": snapshot.pot_odds,
        "spr": snapshot.stack_to_pot,
    }
    if snapshot.to_call == 0 and "check" in snapshot.legal:
        return DecisionIntent("check", None, "free_action", 1.0, features)
    if call_has_margin(snapshot, eq):
        confidence = min(1.0, (eq.equity - snapshot.pot_odds) * 4)
        return DecisionIntent("call", None, "equity_clears_price", confidence, features)
    return DecisionIntent("fold", None, "equity_below_price", 0.8, features)

Execution guard अब भी clamping और fallback का owner है। Active turn बदलने के बाद policy call propose करे तो उसे discard करें। Legal list में न होने वाला raise propose करे तो उसे check या fold से replace करें और policy-violation metric increment करें। Silent correction bugs छिपाती है; telemetry के साथ correction table को safe और failure को visible रखती है।

Hand replays पूरे decision path को कैसे test करते हैं?

Hand replays recorded server events को उसी normalizer और policy से चलाते हैं जो live इस्तेमाल होते हैं, लेकिन socket खोले बिना। वे ऐसे bugs पकड़ते हैं जो isolated unit tests छोड़ देते हैं: hands के बीच leak होती state, empty seat से निकाली गई position, duplicated event या arithmetic तक पहुँचता null amount।

Arrival order सुरक्षित रखते हुए हर line में एक JSON message store करें। Replay runner file load करके real handlers call कर सकता है। Randomness को fixed seed और external services को recorded responses से replace करें। Output decision records की ऐसी sequence होनी चाहिए जिसकी approved behavior से test में तुलना की जा सके।

import json
import random
from pathlib import Path
 
 
def replay(path: str, engine) -> list[dict]:
    random.seed(20260812)
    decisions = []
    for line in Path(path).read_text(encoding="utf-8").splitlines():
        event = json.loads(line)
        result = engine.apply(event)
        if result is not None:
            decisions.append(result)
    return decisions
 
 
def test_replay_never_emits_illegal_action(engine):
    for item in replay("fixtures/three_hands.jsonl", engine):
        assert item["action"] in item["legal"]

Property-based tests action guards के लिए useful हैं। Random legal-action sets और raise bounds generate करें, फिर assert करें कि output हमेशा offered और bounds के भीतर है। Hypothesis इसी testing style के लिए बना है। हर poker opinion के लिए property tests जरूरी नहीं, लेकिन protocol invariants उनके हकदार हैं।

Strategy change को कैसे evaluate करना चाहिए?

Strategy change को paired policies, fixed version labels, operational metrics और uncertainty दिखाने लायक पर्याप्त hands के साथ evaluate करें। New range deploy करके उसके अगले 200 hands की पिछले Tuesday के result से तुलना न करें। Opponent mix, positions और card variance सब बदल चुके होंगे।

कम से कम ये metrics track करें:

Metricयह क्यों मायने रखता है
प्रति 1,000 turns illegal actionsHard correctness gate
Decision latency p50, p95, p99Averages में छिपी tail failures पकड़ता है
Fallback ratePolicy या dependency instability दिखाता है
Confidence interval के साथ bb/100Blinds से normalized strategy outcome
All-in adjusted estimateकुछ showdown variance घटाता है
VPIP, PFR, three-bet rateBehavior कैसे बदला, यह समझाता है
Street के हिसाब से fold rateसाफ strategic leaks पकड़ता है

जहाँ संभव हो simulator में common random numbers इस्तेमाल करें: policy A और B को same deals और opponent actions के against run करें। Live play environment को पूरी तरह control नहीं कर सकता, इसलिए table composition record करें और लंबी windows compare करें। Google DeepMind का OpenSpiel paper imperfect-information games समेत games के लिए evaluation और research framework बताता है। यह locally useful है, जबकि live Open Poker arena protocol और opponent diversity test करता है।

केवल bb/100 positive होने से change promote नहीं होता। उसे correctness gates zero रखने, latency budget के भीतर रखने और कहीं unacceptable regression किए बिना declared target improve करने की जरूरत है।

Advanced level पर LLM कहाँ fit होता है?

LLM उसी policy interface के पीछे selective adviser की तरह fit होता है, network client या legality authority की तरह नहीं। उसे compact snapshot, exact legal actions, calculated pot odds, estimated range और strict JSON schema दें। उसके answer को validate करें और deterministic fallback रखें।

Obvious decisions को model के आसपास route करें। Free check, strict preflop chart से forced fold या deterministic value rule से पहले ही चुना raise size remote call नहीं मांगते। Selective routing cost घटाती है और latency control आसान बनाती है। LLM poker bot guide basic connection pattern दिखाती है, लेकिन advanced runtime में schema validation, versioned prompts, deadline cancellation और replay fixtures भी होने चाहिए।

हम natural-language reasons को evaluation evidence मानने को लेकर skeptical हैं। Model poor action के लिए persuasive explanation बना सकता है। Action को outcomes, counterfactual tests और stable metrics पर judge करें। Text debugging के लिए रखें, लेकिन structured features और experiment record पर भरोसा करें।

FAQ

Poker bot को advanced क्या बनाता है?

Advanced bot immutable turn snapshots, explicit derived features, range-aware equity, opponent statistics, replay tests और versioned experiments इस्तेमाल करता है। केवल ज्यादा strategy code architecture को advanced नहीं बनाता।

Poker bot को कितने Monte Carlo trials run करने चाहिए?

हर decision के लिए 2,000 से 5,000 trials से शुरू करें और अपने hardware पर benchmark करें। ज्यादा trials तभी इस्तेमाल करें जब estimate decisions को इतना बदले कि latency justify हो। Trial count और runtime दोनों log करें।

Opponent modeling के लिए कितना data चाहिए?

पहली observation से smoothing इस्तेमाल करें, लेकिन जब तक हर statistic का meaningful denominator न हो adaptation छोटी रखें। कोई एक magic hand count नहीं है, क्योंकि three-bet opportunities preflop participation opportunities से बहुत कम आती हैं।

Win rate optimize करूँ या chip profit?

Comparable strategy reporting के लिए प्रति 100 hands big blinds और season impact के लिए raw chips इस्तेमाल करें। Uncertainty और operational metrics हमेशा publish करें। Hand count और interval के बिना point estimate false confidence को बुलाता है।

क्या replay tests साबित कर सकते हैं कि poker strategy जीतती है?

नहीं। Replays deterministic behavior साबित करते हैं और known situations में regressions पकड़ते हैं। Simulations और live experiments hands और opponents के distributions के against performance test करते हैं।

जब policy versions, hand replays और metrics हर change को auditable बना दें, अगली constraint operational होती है। Pro Poker Bot Architecture unattended चलने वाले bot के लिए resynchronization, deadline budgets, failure isolation, shadow evaluation और safe releases cover करता है।

और पढ़ो