This example Python script is a bit more complete than the previous one but is not standalone. It also shows how to make calls to a C library.
import argparse
import ctypes
import logging
import os
import re
import sys
import threading
import requests
from .constants import *
from .util import card_string_to_code, pb_to_lib_format
logging.getLogger("urllib3").setLevel(logging.WARNING)
WEB_API_URL = 'https://gtoking.com/api/play'
LIVE_SEARCH = False
CARD_LEN = 2
CLIENT_ID = 0
# If |bet| is None, we just read the current hand state. It is useful at
# the hand's start, as GTO King might play first (and we want to know his move).
# Note that we need to pass |initial_stack| everytime because a same bot can
# play in different formats.
def play(token, initial_stack, bet):
data = {
'token': token,
'initialStacks': [initial_stack, initial_stack],
'game_format': 'hu',
}
if bet is not None:
data['bet'] = bet
response = requests.post(WEB_API_URL, headers={}, json=data)
success = getattr(response, 'status_code') == 200
if not success:
print('Status code: %s' % repr(response.status_code))
try:
print('Error response: %s' % repr(response.json()))
except ValueError:
pass
sys.exit(-1)
try:
r = response.json()
except ValueError:
print('Could not get JSON from response')
sys.exit(-1)
if 'error' in r:
print('Error: %s' % r['error'])
sys.exit(-1)
return r
# This utility can be used to replay the whole history as well. We would have to
# transmit |initial_stack|, |position| and |hole_cards| to do so.
# It is be useful if the bot is very fast and we want the playing robust to
# interruptions.
def replay_history(ai, history):
sub_histos = history.split('/')
for i, sub_histo in enumerate(sub_histos):
# Sequence of bets or board cards.
if i % 2 == 0:
bets = re.findall(r'b(\d+)', sub_histo)
for bet in bets:
bet = int(bet)
ai.ReceiveAction(CLIENT_ID, bet)
else:
assert len(sub_histo) % 2 == 0
cards = [
sub_histo[i:i + CARD_LEN]
for i in range(0, len(sub_histo), CARD_LEN)
]
cards = pb_to_lib_format(cards)
assert len(cards) in [1, 3]
ai.ReceiveNewPublicCards(CLIENT_ID, cards, len(cards))
def play_hand(ai, token, initial_stack):
r = play(token, initial_stack, None)
# print(r)
position = r.get('position')
hole_cards = r.get('hole_cards')
# Unlike Slumbot, our convention is 0 = SB, 1 = BB.
is_bb = position == 1
ai.InitHand(CLIENT_ID, initial_stack, card_string_to_code(hole_cards[0]),
card_string_to_code(hole_cards[1]), is_bb)
# A previous duel was interrupted. Giving up the last hand by check/folding
# (if replaying the whole history is not supported).
if r.get('history').count('b') > 1:
print("Check/folding until hand's end..")
# GTO King should not return an outcome if we didn't send an action
# (except if it was SB and immediately folded, but in such a case there
# is no more than one 'b' in |history|).
assert 'oucome' not in r
while True:
print(r.get('history'))
if 'outcome' in r:
return r['outcome'], r['avg_outcome']
last_street_bets = r.get('history').split('/')[-1]
last_bets = re.findall(r'b(\d+)', last_street_bets)
our_last_bet = 0 if len(last_bets) < 2 else last_bets[-2]
r = play(token, initial_stack, our_last_bet)
# Not reached.
prev_history = ''
while True:
history = r.get('history')
print(history)
if 'outcome' in r:
return r['outcome'], r['avg_outcome']
new_history = history[len(prev_history):]
replay_history(ai, new_history)
bet = ai.PlayAction(CLIENT_ID)
# print('Hero betted', bet)
r = play(token, initial_stack, bet)
prev_history = history + 'b' + str(bet)
# Not reached.
def main():
parser = argparse.ArgumentParser(description='Play versus GTO King')
parser.add_argument('--token', type=str, required=True)
args = parser.parse_args()
token = args.token
lib_path = os.path.join(os.getcwd(), 'build', 'lib',
'libpokerblueprint.so')
ai = ctypes.cdll.LoadLibrary(lib_path)
t = threading.Thread(target=ai.Init,
args=((LIVE_SEARCH, True)),
daemon=True)
t.start()
while t.is_alive():
t.join(.1)
initial_stack = 50
num_hands = 10
session_result = 0
for hand in range(num_hands):
print('\n----------------- HAND %i -----------------' % (hand + 1))
hand_result, lifetime_result = play_hand(ai, token, initial_stack)
session_result += hand_result
print('Total session:', session_result)
print('Total lifetime:', lifetime_result)
if __name__ == '__main__':
main()