Writing Poker Bots for the Poki Poker Server
Online Poker Protocol (v1.1)
Updated March 26th 2004, Aaron Davidson
Poker AI programs need a way to play each other -- both for tournaments,
gathering empirical data, and playing against humans online. This
protocol is currently for fixed limit Texas Hold'em. Later, it will be
expanded to handle other variants such as pot limit and no limit.
New: Also check out the commercial product Poki's Poker Academy
which has a plug-in API for adding and testing your own custom bots against poki.
This protocol consists of simple messages being passed from server
to client. The server hosts the game, the client acts as a player in a
game. If you are familiar with the IRC poker system, this has a similar
high level architecture, except the IRC layer is removed and replaced
with a poker specific layer of communications.
The full details of the protocol are documented here, but source
code (see section 5 below) that implements many of the lower level
details will be provided. Anyone is welcome to implement their programs
from scratch, but the provided source code should make it much easier to
get your poker program to support the protocol.
Please send
suggestions to davidson@cs.ualberta.ca
Bot Rules & Etiquette
Your bots are guests on our server, which we use as a way to gather
experimental results on our own bots. Please repsect the following:
- For all testing, play in the bots-only room. If your bot is slow,
crashes frequently, or plays very badly, do not play in the rooms
designated for humans. Humans are extremly annoyed by slow bots. We do
not want to chase away our human players as they provide the best
measure of performance. Likewise, if your bot is stupidly raising every
hand, etc..., this is also very annoying. Furthermore, we do not want
super-weak players in the game feeding both our bots and the humans.
This vastly inflates the winnings of all good players, which interferes
with our main goal of getting reliable experimental results. Novelty
bots (we have seen many on our servers) simply waste our time, and
occupy a seat that other, valid players could hold.
- If the room is full, periodically (after an hour or so) log off for
five minutes to allow other players to take the seat. This will allow
players waiting in line to have a chance to play.
- If a player chats "YourBotName please leave", and the game is full,
consider having your bot log out at the end of the current hand, so that
player can play.
- It is our convention to suffix the name of your program with 'bot',
(i.e., Pokibot, RotnBot, etc...). Please do so to signify that the
player is a bot. Please also register your bot with
davidson@cs.ualberta.ca -- and I can give the bot a special player icon
that looks like a robot.
- Only one bot at a time please! Do not have multiple bots playing in
the same room. Multiple bots are suspicious, and are hogging seats.
- Until you need data against humans, play in the bots-only room.
There is no point in taking up seats in the human games until your bot
is ready. It should be able to at least break even in the bots-only
game before being ready to play the humans.
- We would really appreciate it if bot writers would email us and tell
us a little about your bot (As much as you are comfortable divulging).
We would love to hear the techniques and strategies you use, and how well they
are working, plus any other interesting experiences.
Bot Servers
A listing of the current poker servers can be found here:
Server Listing giving the address, port
and room title.
Source Code
- Unix C bot source contains C source code
that implements the above protocol.
Thanks to Chris Sells for
making the code Windows compatible.
Note: This code is provided as an example of implementing the
protocol only. It is slightly buggy, and doesn't track the game
state very well. Please use it with caution. The
java BotPlayer
class is much more robust if you are looking for a solid implementation.
- Perl bot source was written by
Vince Hurrell.
Message Passing
Messages are passed by writing the following to a TCP/IP socket stream:
- a four byte integer containing the ID of a message
- a four byte integer containing the size of the message data
- the message data itself
Source code that implements all of this message passing, and networking
details is available in Java and in C (for UNIX Sockets). Minor changes
should allow the C code to compile under Windows.
Logging on to the Server
Once the low level message passing is dealt with, the protocol simply becomes
a matter of passing the right messages back and forth from the client to the
server. The various messages have been assigned farily arbitrary numerical values. Each message has a defined format, given below. Strings are c-style, null terminated. Integers are 4-bytes long.
The first step is to log on to the server by establishing a connection and logging onto the poker server.
For each message listed below, the number in square brackets next to the message name
is the message ID.
You do not need to obtain a user name and password -- simply log on
using your name and password of choice, and if the name is not yet
taken, a new account will be created automatically.
[20] JOIN_GAME |
String |
userid |
the user id the client will play under |
String |
passwd |
the password for the given userid |
int |
version |
Protocol Version (1) |
String |
client_name |
The name of your program (optional) |
|
If the password is incorrect, the server will respond with a
BADPASS message otherwise it will respond with a GOODPASS message.
|
[21] GOODPASS |
|
Authentication successful. Proceed to main game loop.
|
[22] BADPASS |
|
Authentication failed.
|
[24] BADNICK |
|
Authentication failed (nickname is not of proper length
or contains illegal characters)
|
Server Game Updates
After a successful authentication, we enter the main game loop.
The server will send all queued game update messages to the client
Below are the possible messages the server may send:
[50] START_NEW_GAME |
int |
bet_size |
the starting bet size (eg. 10 in a 10-20 game) |
int |
num_players |
the number of players in the game |
int |
button |
the position of the button |
int |
position |
your position (index into player data sent below,
or -1 if you are not dealt in) |
int |
gameID |
ID number for this hand |
for each player: |
String |
player_name |
the userid of the nth player |
int |
bankroll |
the bankroll of the nth player |
int |
face |
face icon ID (used for display in Applet) |
[51] HOLE_CARDS |
int |
who |
the player whose cards are being revealed |
String |
hole_cards |
eg: "Ah 5c" |
if who is equal to your position, then this is used to send
you your hole cards. Otherwise, it is used to reveal a player's
hand in a showdown.
|
[52] NEW_STAGE |
int |
round |
(FLOP == 1, TURN == 2, RIVER == 3) |
String |
board_cards |
board cards. eg: "Jd Ks 3s 3h" |
[57] NEXT_TO_ACT |
int |
who |
the player to act |
int |
to_call |
the amount to call |
int |
min_bet |
the smallest bet allowed
(-1 if no more raises) |
int |
max_bet |
the largest bet allowed
(-1 if no more raises) |
[3] BLIND, [0] FOLD, [1] CALL, [2] RAISE
|
int |
who |
the player who has acted |
int |
amount |
amount ($) paid to the pot (if applicable) |
[53] WINNERS |
int |
num_winners |
number of winners |
for each winner: |
int |
who |
the position of the nth winner |
int |
share |
the nth winner's share of the pot |
[54] CHATTER |
String |
chat |
a chat message from another player |
[43] INFORMATION |
String |
info |
an informational message from the server |
[60] PING |
| This is sent when the server wants to
see if you are still alive. You can respond with a PONG
or any other message (optional). |
[45] SET_FACE |
String |
who |
the face ID of the player
Faces can be loaded from the webserver at
./data/faces/pX.gif where X is the ID number
of the face.
|
Client Game Updates
The following are the messages that a client player may send
to the server.
[30] ACTION |
int |
action |
(FOLD == 0, CHECK/CALL == 1, BET/RAISE == 2) |
[32] CHAT |
String |
chat_string |
say something to all other players in the game |
[33] QUIT_GAME |
|
Tells the server to remove you from the table, and closes
your connection.
|
[61] PONG |
| This will tell the server you are still alive.
|
Non-critical extra-fun messages
[47] CHANGE_FACE |
int |
delta |
Send +1 or -1 to change to the next or
previous face. |
[46] GET_FACE |
String |
who |
Get face id of 'who'
(returns a SET_FACE message) |
[42] GET_GRAPH |
String |
who |
Ask the server to generate a graph
(Sever will respond with a GET_GRAPH with two strings
giving the name and the file path of the .gif image) |