Skip to content
[OPEN_POKER]

Bots के लिए Poker Math: Pot Odds, Position, और Hand Strength

JJoão Carvalho||11 min read

एक poker bot जो तीन चीज़ें समझता है (pot odds, position, और starting hand strength) वो 80% बिना इनके bots को beat कर लेगा। मैंने Open Poker के 6-max No-Limit Hold'em platform पर हज़ारों hands देखे हैं, और pattern consistent है: ज़्यादातर bots इसलिए हारते हैं क्योंकि वो basic math ignore करते हैं, sophisticated algorithms की कमी से नहीं।

मैं Open Poker चलाता हूँ, जहाँ AI bots 10/20 blinds पर 14-day seasons में compete करते हैं। Fundamentals के लिए neural networks की ज़रूरत नहीं। सिर्फ arithmetic। ये post उन तीन concepts को cover करती है जो सबसे ज़्यादा matter करते हैं, Python code के साथ जो तुम directly अपने bot में use कर सकते हो। अगर तुम ये math real-time opponent tracking के साथ combine करना चाहते हो, तो इस post के बाद opponent modeling tutorial पढ़ो।

Pot odds कैसे काम करते हैं?

Pot odds एक single question का answer देते हैं: "क्या ये call long run में profitable है?" Math simple है। जो amount तुम्हें call करना है उसे total pot से divide करो (तुम्हारे call के बाद)। अगर तुम्हारी winning probability उस number से ज़्यादा है, तो call करो। नहीं तो fold।

pot_odds = call_amount / (current_pot + call_amount)

Open Poker पर, your_turn message तुम्हें सब कुछ देता है: pot (current pot size) और valid_actions में call entry (exact call amount)। Betting history track करने की ज़रूरत नहीं; सब एक message में है। Full structure के लिए message types reference देखो।

def should_call(your_turn_msg, win_probability):
    pot = your_turn_msg["pot"]
    call_amount = 0
    for action in your_turn_msg["valid_actions"]:
        if action["action"] == "call":
            call_amount = action["amount"]
            break
    if call_amount == 0:
        return True  # Free check, always take it
    pot_odds = call_amount / (pot + call_amount)
    return win_probability > pot_odds

10/20 game का real example: Pot में 200 chips हैं और तुम्हारा opponent 100 bet करता है। तुम्हें 100 call करना है एक pot में जो 400 होगा। तुम्हारे pot odds हैं 100/400 = 25%। अगर तुम सोचते हो कि तुम 25% से ज़्यादा बार जीतोगे, तो call correct है। Turn पर flush draw के साथ (roughly 19% chance river पर hit करने का), fold। Flush draw plus एक overcard के साथ (roughly 30%), call। Pot odds हर profitable decision tree की foundation हैं।

जो mistake मैं सबसे ज़्यादा देखता हूँ: bots जो हर bet पर call करते हैं pot odds की परवाह किए बिना। जब hit करते हैं तो जीतते हैं, लेकिन बहुत सारे losing spots में भी pay करते हैं। Season 1 (March 2026) में, बिना pot odds logic वाले bots ने 500+ hands में 3-5 bb/100 खोए — इतना काफी था leaderboard के middle से bottom तक गिरने के लिए। ये bad luck नहीं है। ये math का problem है। अगर और deep जाना चाहते हो, तो implied odds glossary entry दिखाता है कि pot odds math को कैसे extend करें उन draws के लिए जो बाद की streets पर और ज़्यादा जीतने की expect करते हैं।

Position इतना important क्यों है?

Position poker में सबसे underrated edge है। जो player last में act करता है उसने decide करने से पहले सभी players की action देख ली होती है। वो information chips की value रखती है, और hundreds of hands में compound होती है।

Open Poker पर 6-max game में, positions ये हैं:

PositionDealer से relative seatAdvantage
UTG (Under the Gun)Pre-flop में 1st actसबसे खराब: कोई information नहीं
HJ (Hijack)2nd actखराब
CO (Cutoff)3rd actअच्छी
BTN (Button/Dealer)Post-flop में last actसबसे अच्छी: maximum information
SB (Small Blind)10 post करता है, post-flop में पहले actखराब: forced investment + bad position
BB (Big Blind)20 post करता है, सिर्फ pre-flop में last actModerate: सारी pre-flop action देखता है

तुम अपनी position hand_start message से determine कर सकते हो। ये तुम्हें dealer_seat (button) और seat (तुम्हारा seat number) देता है। Button से clockwise गिनो अपनी relative position find करने के लिए।

def get_position(my_seat, dealer_seat, num_players):
    """Return position name based on seat distance from dealer."""
    # Count seats clockwise from dealer
    distance = (my_seat - dealer_seat) % num_players
    if num_players <= 3:
        positions = {0: "BTN", 1: "SB", 2: "BB"}
    else:
        positions = {
            0: "BTN",
            1: "SB",
            2: "BB",
            3: "UTG",
            4: "HJ" if num_players > 4 else "UTG",
            5: "CO" if num_players > 5 else "HJ",
        }
    return positions.get(distance, "UTG")

Practical takeaway: Early position (UTG, HJ) में tighter खेलो, late position (CO, BTN) में wider। K9 suited जैसी hand UTG से fold है लेकिन button से raise। Platform का data दिखाता है कि position के हिसाब से opening ranges adjust करने वाले bots late position से early position की तुलना में 1.5-2x ज़्यादा chips per hand जीतते हैं। Information asymmetry real है और हर season में consistent है। Honestly, मुझे नहीं लगा था कि position bot-vs-bot play में इतना matter करेगा। मुझे लगा था bots positionally humans से कम exploitable होंगे। मैं गलत था। Position hand selection के बाद सबसे important factor है, और मैं इसे overall win rate impact में pot odds से ऊपर rank करूंगा। Position और stack depth के interaction के बारे में और जानने के लिए, stack-to-pot ratio (SPR) glossary entry देखो।

Starting hands को कैसे evaluate करें?

सारी 169 distinct starting hands equal नहीं हैं। Pocket aces heads-up में लगभग 85% बार जीतते हैं। Seven-two offsuit लगभग 35%। ज़्यादातर hands कहीं बीच में आती हैं, और "playable" और "unplayable" के बीच का gap वही है जहाँ chips बनते या जाते हैं।

एक simple ranking system जो 6-max के लिए अच्छा काम करता है, loosely based on Chen formula for hand valuation:

def hand_rank(cards):
    """Score a 2-card hand from 0.0 (worst) to 1.0 (best).
 
    Uses Chen formula approximation: accounts for rank, suitedness,
    pair bonus, and connectedness.
    """
    ranks = "23456789TJQKA"
    r1 = ranks.index(cards[0][0])
    r2 = ranks.index(cards[1][0])
    high, low = max(r1, r2), min(r1, r2)
    suited = cards[0][1] == cards[1][1]
    pair = r1 == r2
 
    # Base score from high card
    score = (high + 1) / 13
 
    # Pair bonus (pairs are strong)
    if pair:
        score = 0.5 + (high / 24)
        return min(1.0, score)
 
    # Suitedness bonus (flush potential)
    if suited:
        score += 0.06
 
    # Connectedness bonus (straight potential)
    gap = high - low
    if gap == 1:
        score += 0.04
    elif gap == 2:
        score += 0.02
 
    # Second card contribution
    score += (low / 26)
 
    return min(1.0, max(0.0, score))

इस scoring के साथ:

  • AA → 1.0, KK → 0.96, QQ → 0.92 (premium pairs)
  • AKs → 0.87, AKo → 0.81 (big aces)
  • T9s → 0.57, 87s → 0.49 (suited connectors)
  • 72o → 0.12 (poker की सबसे बुरी hand)

एक simple strategy: किसी भी position से 0.45 से ऊपर वाली hands खेलो, late position से 0.35 से ऊपर। 0.7 से ऊपर वाली hands raise करो। ये GTO-optimal नहीं होगा, लेकिन हर उस bot को beat करेगा जो starting hands filter ही नहीं करता। और ये field का surprisingly बड़ा हिस्सा है।

तीनों को कैसे combine करें?

हर your_turn के लिए decision tree ये बनता है:

  1. Pre-flop: Hand rank + position check करो। Weak hands fold, medium hands call, strong hands raise। Position के हिसाब से thresholds adjust करो।
  2. Post-flop: Win probability estimate करो (rough काफी है: top pair ≈ 60%, draw ≈ 30%, nothing ≈ 15%)। Pot odds से compare करो। Profitable है तो call, नहीं तो fold। Strong हो और pot build करना चाहते हो तो raise।
def decide(your_turn_msg, my_cards, my_position):
    actions = {a["action"]: a for a in your_turn_msg["valid_actions"]}
    board = your_turn_msg.get("community_cards", [])
    pot = your_turn_msg["pot"]
 
    if len(board) == 0:
        # Pre-flop
        strength = hand_rank(my_cards)
        threshold = 0.45 if my_position in ("UTG", "HJ", "SB") else 0.35
 
        if strength > 0.7 and "raise" in actions:
            return {"action": "raise", "amount": actions["raise"]["min"]}
        if strength > threshold:
            return {"action": "call"} if "call" in actions else {"action": "check"}
        return {"action": "fold"} if "fold" in actions else {"action": "check"}
 
    # Post-flop: simplified pot odds
    if "check" in actions:
        return {"action": "check"}
    if "call" in actions:
        call_amt = actions["call"]["amount"]
        pot_odds = call_amt / (pot + call_amt)
        # Rough: call if pot odds are better than 35% (we assume ~35% equity with a draw/pair)
        if pot_odds < 0.35:
            return {"action": "call"}
    return {"action": "fold"}

ये roughly 30 lines का decision logic है। Leaderboard top नहीं करेगा, लेकिन हमारी testing में top 40% में आता है — किसी भी pure calling station और ज़्यादातर random action वाले bots से बेहतर। Actions guide raise amounts, turn tokens, और valid action handling detail में cover करता है।

Next level क्या है?

ऊपर के तीन concepts तुम्हें "competent" level तक ले जाते हैं। Leaderboard के top पर पहुँचने के लिए, तुम्हें rough heuristics की जगह hand equity accurately estimate करनी होगी। Standard approach है Monte Carlo simulation।

Idea simple है: तुम्हारे hole cards और board को देखते हुए, बाकी cards को randomly हज़ारों बार deal करो और गिनो कि कितनी बार तुम जीतते हो। वो win rate तुम्हारी equity है। यहाँ एक sketch है:

import random
import itertools
 
RANKS = "23456789TJQKA"
SUITS = "shdc"
FULL_DECK = [r + s for r in RANKS for s in SUITS]
 
def estimate_equity(hole_cards, board, num_opponents=1, simulations=2000):
    """Estimate win probability via Monte Carlo simulation."""
    known = set(hole_cards + board)
    deck = [c for c in FULL_DECK if c not in known]
 
    wins = 0
    for _ in range(simulations):
        sample = random.sample(deck, (5 - len(board)) + num_opponents * 2)
        remaining_board = board + sample[: 5 - len(board)]
        opp_cards = sample[5 - len(board) :]
 
        my_best = best_hand(hole_cards + remaining_board)
        opp_best = best_hand(opp_cards[:2] + remaining_board)
 
        if my_best > opp_best:
            wins += 1
        elif my_best == opp_best:
            wins += 0.5  # Chop
 
    return wins / simulations

तुम्हें एक best_hand() function चाहिए होगा जो 5-card hand score करे; treys या deuces जैसी libraries ये कुछ lines में कर देती हैं। 2,000 simulations पर, ये modern CPU पर per decision 50ms से कम में चलता है — 120-second action timeout के अंदर easily। 500 simulations पर 15ms से कम, ज़्यादातर spots के लिए काफी accurate।

Monte Carlo के आगे, असली game-changers ये हैं:

  • Opponent modeling: player_action messages use करके track करो कि हर opponent अलग situations में कितनी बार bet, call, और fold करता है
  • Bet sizing: हमेशा min-raise करने की जगह board texture और opponent tendencies के basis पर raise amounts vary करो
  • Counterfactual regret minimization (CFR): Libratus और Pluribus के पीछे का algorithm, poker AI का gold standard। 2019 का Pluribus paper Science में पढ़ने लायक है अगर तुम समझना चाहते हो कि state-of-the-art कैसा दिखता है

हम इनमें से हर एक को future posts में cover करेंगे। अभी के लिए, pot odds + position + hand strength implement करो और अपने bot को ऊपर जाते देखो।


Test करने के लिए तैयार हो? एक bot register करो और current season join करो। या पहले tutorial पढ़ो: Python में 50 Lines से कम में Poker Bot बनाओ


FAQ

मेरी win probability estimate कितनी accurate होनी चाहिए? एक rough estimate (top pair ≈ 60%, draw ≈ 30%, nothing ≈ 15%) उन bots को beat करने के लिए काफी है जो pot odds logic use नहीं करते। Leaderboard के top के लिए, तुम्हें ऊपर describe की गई Monte Carlo simulation चाहिए होगी; rough numbers close spots में chips table पर छोड़ देते हैं।

क्या मुझे GTO (Game Theory Optimal) strategy use करनी चाहिए? Open Poker के 10/20 blind level पर, exploitative play (opponent tendencies के हिसाब से adjust करना) GTO से जीतती है। GTO दूसरे GTO players के against सबसे strong है। Platform पर ज़्यादातर bots के exploitable patterns हैं; उनका फायदा उठाओ। Tight-aggressive heuristic consistently एक badly-implemented GTO solver को outperform करती है।

मैं अपने bot के stats कहाँ देख सकता हूँ? Season dashboard तुम्हारा chip balance, hands played, win rate, और leaderboard rank दिखाता है। Premium users को rolling win-rate charts और session P&L graphs मिलते हैं।

अगर ये सब implement करने के बाद भी मेरा bot हारता रहे तो? Variance real है। Correct decisions लेने वाला bot भी 200 hands में हार सकता है और फिर भी optimally खेल रहा हो सकता है। Performance 1,000+ hands पर judge करो, single sessions पर नहीं। एक खराब river card signal नहीं है।

और पढ़ो