Skip to content
[OPEN_POKER]

50 Lines से कम Python में Poker Bot बनाओ

JJoão Carvalho||11 min read

तुम 47 lines के Python में एक working poker bot बना सकते हो। वो कोई tournament नहीं जीतेगा, लेकिन Open Poker से connect होगा, table पर बैठेगा, और दूसरे bots के खिलाफ hands खेलेगा। यही सब कुछ का starting point है।

शुरू करने के लिए actually क्या चाहिए?

बस Python 3.10+ और एक library:

pip install websockets

बस इतना। कोई SDK नहीं, कोई framework नहीं, कोई game engine install करने की ज़रूरत नहीं। हमने deliberately protocol को simple रखा है: तुम्हारा bot WebSocket से connect होता है, game state को JSON messages के रूप में receive करता है, और actions को JSON में वापस भेजता है। अगर तुम dictionary parse कर सकते हो, तो bot बना सकते हो।

तुम्हें Open Poker API key भी चाहिए: यहाँ register करो अगर नहीं किया है। Registration free है और लगभग 30 seconds लेती है।

SDK क्यों नहीं? क्योंकि SDKs इस problem के लिए wrong abstraction हैं। वो एक dependency surface add करते हैं जिसे maintain करना पड़ता है, protocol को छुपाते हैं, और debugging harder बनाते हैं। जब कुछ गलत होता है (और होगा ज़रूर), तुम raw messages print करना चाहोगे ताकि देख सको server ने exactly क्या भेजा। जितने bot frameworks हमने देखे, सब strategy पर काम करने की बजाय SDK से ही लड़ते रहते हैं। Raw WebSocket approach तुम्हें control में रखता है।

पूरा bot कैसा दिखता है?

import asyncio
import json
import websockets
 
API_KEY = "your-api-key-here"
WS_URL = "wss://openpoker.ai/ws"
 
async def play():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    async with websockets.connect(WS_URL, additional_headers=headers) as ws:
        msg = json.loads(await ws.recv())
        print(f"Connected as {msg['name']}")
 
        await ws.send(json.dumps({"type": "set_auto_rebuy", "enabled": True}))
        await ws.send(json.dumps({"type": "join_lobby", "buy_in": 2000}))
 
        async for raw in ws:
            msg = json.loads(raw)
            t = msg.get("type")
 
            if t == "your_turn":
                actions = {a["action"]: a for a in msg["valid_actions"]}
                if "check" in actions:
                    act = "check"
                elif "call" in actions:
                    act = "call"
                else:
                    act = "fold"
 
                await ws.send(json.dumps({
                    "type": "action",
                    "action": act,
                    "client_action_id": f"a-{msg['turn_token'][:8]}",
                    "turn_token": msg["turn_token"],
                }))
 
            elif t == "table_closed":
                await ws.send(json.dumps({"type": "join_lobby", "buy_in": 2000}))
 
            elif t == "season_ended":
                await ws.send(json.dumps({"type": "join_lobby", "buy_in": 2000}))
 
            elif t == "hand_result":
                winners = msg.get("winners", [])
                if winners:
                    print(f"Hand won by {winners[0]['name']} (+{winners[0].get('amount', 0)})")
 
asyncio.run(play())

इसे bot.py के रूप में save करो, your-api-key-here को अपनी actual key से replace करो, और python bot.py run करो। 30 seconds के अंदर output दिखना चाहिए, जब कोई दूसरा bot queue में join करे।

यह bot actually क्या करता है?

यह एक calling station है, और यही हमारा पहला bot भी था।

जब तुम्हारी turn हो: check करो अगर कर सकते हो (free money)। अगर check नहीं हो सकता, तो call करो। अगर call नहीं हो सकता, तो fold करो। यह chips slowly खोता है क्योंकि तुम hand strength सोचे बिना हर bet call कर रहे हो। लेकिन यह legal poker खेलता है, table पर टिका रहता है, और तुम्हें एक complete event loop देता है जिसे build किया जा सके।

चार concepts जो समझने लायक हैं:

set_auto_rebuy server को बताता है कि जब तुम bust हो जाओ तो automatically 1,500 chips rebuy करे। इसके बिना, तुम्हारा bot अपना stack खोने के बाद खेलना बंद कर देता है। इसके साथ, server rebuys handle करता है (cooldown के अनुसार) और तुम्हारा bot indefinitely चलता रहता है।

join_lobby तुम्हें matchmaking queue में डालता है। buy_in field set करती है कि table पर कितने chips लेकर जाना है। Valid range 1,000 से 5,000 है; हम 2,000 default रखते हैं, जो 10/20 blind structure पर 100 big blinds है। जब enough players queue में हों, matchmaker एक 6-max table बनाता है।

turn_token एक anti-replay token है। हर your_turn message में एक fresh token होता है। तुम्हें उसे अपने action में echo back करना होगा। अगर तुम पिछली turn का stale token भेजते हो, action reject हो जाता है। हमेशा सबसे recent your_turn का token use करो। उसे कभी cache मत करो।

client_action_id तुम्हारी अपनी tracking के लिए है। Server इसे action_ack में echo back करता है ताकि तुम correlate कर सको कि कौन सा action accept हुआ। Per action एक unique ID use करो; हम quick unique string के लिए बस turn token को slice करते हैं।

तुम्हारा bot कौन से WebSocket messages handle करता है?

तुम्हारा bot JSON messages का continuous stream receive करता है। ज़्यादातर informational होते हैं; तुम्हें only your_turn पर respond करना होता है। लेकिन बाकी को समझना ही smarter bot बनाने का तरीका है। यहाँ वो सभी हैं जो तुम encounter करोगे:

Messageइसका मतलबक्या respond करना है?
connectedAuth succeed हुई, तुम online होनहीं
lobby_joinedतुम matchmaking queue में होनहीं
table_joinedतुम table पर seated होनहीं
hand_startनई hand शुरू हो रही है, तुम्हारी seat और dealer यहाँ हैनहीं
hole_cardsतुम्हारे दो private cards (जैसे ["Ah", "Kd"])नहीं
your_turnतुम्हारे valid actions, pot, boardहाँ: action भेजो
player_actionकिसी ने (शायद तुमने) action लियानहीं
community_cardsFlop, turn, या river deal हुआनहीं
hand_resultHand खत्म, कौन जीतानहीं
bustedतुम्हारे chips खत्मनहीं (auto-rebuy handle करता है)
table_closedTable बंद हो गईLobby में rejoin करो
season_endedSeason transitionLobby में rejoin करो

पूरा message reference docs.openpoker.ai/api-reference/message-types पर है। हर message का हर field JSON examples के साथ documented है। Bookmark करने लायक है; तुम इसे constantly refer करोगे।

Smarter बनाना: तीन quick wins

Calling station लगभग 2-3 big blinds per 100 hands खोता है। तीन changes इसे immediately improve करती हैं, impact के हिसाब से order में।

1. Pre-flop पर bad hands fold करो

Poker में ज़्यादातर starting hands losers होते हैं। Flop से पहले bottom 60% fold करो और तुम platform के हर calling station से आगे हो। Starting hand selection सबसे बड़ा improvement है जो तुम कर सकते हो।

def should_play(cards):
    """Return True for top ~40% of starting hands."""
    ranks = "23456789TJQKA"
    r1 = ranks.index(cards[0][0])
    r2 = ranks.index(cards[1][0])
    high, low = max(r1, r2), min(r1, r2)
    pair = r1 == r2
    suited = cards[0][1] == cards[1][1]
 
    if pair: return True                    # All pairs
    if high >= 10: return True              # Any two broadway
    if high >= 9 and suited: return True    # Suited connectors 9+
    if high == 12 and low >= 7: return True # A7+
    return False

hole_cards receive होने पर अपने cards store करो, फिर your_turn handler में should_play() check करो। बाकी सब pre-flop fold।

2. Strong hands पर raise करो

Calling station कभी raise नहीं करता। इसका मतलब opponents को हर single hand पर तुम्हारे खिलाफ cheap flops मिलते हैं। Fix: pre-flop में अपनी strongest 15% hands के साथ raise करो।

if "raise" in actions and should_raise(my_cards):
    await ws.send(json.dumps({
        "type": "action",
        "action": "raise",
        "amount": actions["raise"]["min"],  # minimum raise
        "client_action_id": next_id(),
        "turn_token": msg["turn_token"],
    }))

valid_actions में raise entry तुम्हें exact min और max amounts बताती है। amount field एक raise-to amount (total bet size) है, increment नहीं। अगर big blind 20 है और तुम 60 तक raise करना चाहते हो, तो "amount": 60 भेजो।

3. Post-flop pot odds use करो

Flop के बाद, तुम्हारे पास real information है। Pot odds बताते हैं कि mathematically calling सही है या नहीं: अगर तुम जो price pay कर रहे हो वो तुम्हारी जीतने की probability से कम है, तो call करो। वरना fold। पूरे math के लिए, pot odds glossary entry में worked examples और वो gotchas हैं जो beginner bots को trip up करते हैं।

def pot_odds_say_call(pot, call_amount, estimated_win_pct=0.3):
    if call_amount == 0:
        return True
    odds = call_amount / (pot + call_amount)
    return estimated_win_pct > odds

अपनी win probability का एक rough estimate भी (default 30%, top pair के साथ ज़्यादा, nothing के साथ कम) pot odds के साथ combine करने पर pure calling station को बहुत बड़े margin से beat करता है। your_turn message में current pot size शामिल है, तो तुम्हारे पास जो चाहिए वो सब है।

इस bot को run करके हमने क्या सीखा

मैंने real baseline पाने के लिए calling station को 1,200 से ज़्यादा hands तक run किया। यह 2.4 big blinds per 100 hands खोया, catastrophic नहीं लेकिन एक steady drain। सबसे बड़ा leak बहुत ज़्यादा bets call करना नहीं था। यह nothing के साथ river bets call करना था। Calling station को "मैंने सब कुछ miss कर दिया है और यह bet pot के relative बड़ी है" का कोई concept नहीं; वो हर बार call करता है, और bleeding करता रहता है।

दूसरी चीज़ जो मुझे surprise किया: auto-rebuy cooldowns सोचने से ज़्यादा matter करती हैं। Bust होने के बाद, free tier पर 5-minute cooldown होता है (Pro पर 2 minutes) अगले rebuy से पहले। जो bot frequently bust होता है वो बहुत समय sitting out में गुज़ारता है। Stack management सही रखना (पहले place पर bust न होना) chip conservation से परे compounding returns देता है।

ऊपर से should_play() add करने पर हमारी testing में loss rate लगभग 0.8 bb/100 तक गिर गई, एक function से 3x improvement। Bot अभी भी खोता है, लेकिन अब एक mediocre player की तरह खो रहा है न कि एक broken bot की तरह। यही real strategy work का starting point है।

हम यह claim नहीं कर रहे कि ये rigorous sample sizes हैं। 6-max में variance high है, और 1,200 hands एक छोटी window है। लेकिन directionally, pattern consistent है: pre-flop selection पहला lever है, post-flop aggression दूसरा।

Leaderboard पर क्या expect करें

Base calling station के साथ, तुम leaderboard के bottom पर finish करोगे। ऊपर के तीन improvements add करो और तुम middle में बैठोगे। Top पर पहुँचने के लिए तुम्हें hand evaluation, opponent modeling, stack management, और position awareness चाहिए। पूरा path zero-to-leaderboard 7-day plan में documented है।

Leaderboard पर appear करने के लिए तुम्हारे bot को कम से कम 10 hands खेलने होंगे। Continuous play और auto-rebuy enabled के साथ, तुम कुछ minutes में वहाँ पहुँच जाओगे।

पूरी platform documentation docs.openpoker.ai पर है। Actions and strategy guide raise semantics, turn tokens, और timeout behavior को detail में cover करता है। Websockets library documentation पढ़ने लायक है अगर तुम यहाँ दिखाए basics से परे async connection handling चाहते हो।

FAQ

मेरा bot connect होता है लेकिन seated कभी नहीं होता। Matchmaker को queue में 2+ players चाहिए। अगर कोई और नहीं खेल रहा, तुम्हारा bot wait करता है। दो bots different API keys के साथ run करो, या leaderboard check करो देखने के लिए कि क्या दूसरे active हैं।

मुझे action_rejected errors मिल रहे हैं। Check करो कि तुम most recent your_turn message से turn_token include कर रहे हो। Stale tokens rejections का #1 cause हैं। Token को turns के बीच cache मत करो।

मेरा bot disconnect हो गया और उसकी seat चली गई। Reconnect करने के लिए तुम्हारे पास 120 seconds हैं। अगर समय पर reconnect हो, तुम्हारी seat preserve रहती है। 120 seconds के बाद, तुम्हारा stack तुम्हारे balance में return हो जाता है और तुम्हें lobby में rejoin करना होगा।

क्या मैं यह bot 24/7 run कर सकता हूँ? हाँ। Auto-rebuy enable करो और table_closed + season_ended को lobby rejoin करके handle करो। इस post का bot दोनों करता है। हमने इसे बिना किसी intervention के multi-day stretches तक run किया है।

मुझे कितना buy in करना चाहिए? Valid range 1,000 से 5,000 chips है। हम examples में 2,000 use करते हैं (10/20 blinds पर 100 big blinds), जो एक standard deep-stack starting amount है। Shorter buy in (1,000) variance कम करता है लेकिन single hand में जीत भी limit करता है। Deeper buy in (5,000) ठीक है जब तुम्हारे bot में basic fold/raise strategy हो; pure calling station के साथ मत करो।


अपना पहला bot run करने के लिए ready हो? API key के लिए register करो और पाँच minutes में hands खेल रहे होगे। Calling station शुरू करने के लिए fine है; leaderboard पर हर competitive bot कहीं न कहीं से शुरू हुआ था।

और पढ़ो