Ruby Poker Server using Spire.IO
Ruby
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
bots
poker
server
shared_bot_code
utils
.gitignore
README.textile
config_example.rb

README.textile

PokerMatic

PokerMatic consists of two parts; a server and a set of bot libraries. The server can be thought of
as the virtual poker hall; it is in charge of setting up tables, giving chips to players, and dealing the cards.
The bot libraries can be thought of as the virtual poker players, playing at tables hosted by the server.

Setting up the dependencies

Both the PokerServer and PokerBots require the same following dependencies:

  • JRuby is recommended for threading performance
  • Install the spire.io.rb gem (https://github.com/spire-io/spire.io.rb)
    • jgem install bundler
    • jgem install spire_io
  • Install OpenPGP and Gibberish (for encryption)
    • jgem install openpgp
    • jgem install gibberish

Setting up your config file

Both the server and client libraries read their settings from a file config.rb. Make a copy
of config_example.rb and name it config.rb in the root directory of PokerMatic.

To run a server, the only values that you need to set are SPIRE_EMAIL and SPIRE_PASSWORD This should be your spire.io
credentials. (You can sign up for a spire.io account at http://www.spire.io/register.html) If an account doesn’t exist for that email,
a new account will be created.

Once the poker server is started (by running bin/poker_server), an APP_KEY will be displayed.
This is the value that clients will need in order to connect to the server.
Copy the displayed line into your config file. If you are connecting
to a poker server running somewhere else, you will need their APP_KEY to connect.

Running a poker server

Starting up the poker server is as simple as running bin/poker_server. Since all communication
occurs through spire.io, there is no need to worry about DNS, IP addresses, or port forwarding.
The only thing clients will need is the APP_KEY that is displayed when the server starts up.

Here is an example output when a server starts up:

>$ bin/poker_server.rb
Starting up server
Server running:
APP_KEY = 'Ap-JQY'

Simply copy the last line printed into your config.rb file

Connecting a bot to the server

You then have two ways to run a bot; as a single bot by running bin/bot or as a cluster of bots by running bin/bot_cluster.
First make sure you have set your APP_KEY in your config.rb to match the server you are trying to
connect to, and then run either bin/bot or bin/bot_cluster; bin/bot will ask you which class of bot you want to run, while bin/bot_cluster
will ask how many bots of each class you want to run. After the bots are created, you will be given the choice to either create a new table,
join an existing table, or join a tournament.

Here is an example from bin/bot:

>$ bin/bot
Choose a bot:
1: AllInBot
2: HumanClient
3: RandomBot
4: SmartBot
5: SuperSteadyBot
Choose a bot class:
> 2
Player name?
> Daniel
Tournament or table? (1 = tournament, 2 = table)

Creating and joining a table

With both bin/bot and bin/bot_cluster, after the bots are created you will be given the option to create or join a table:

Tournament or table? (1 = tournament, 2 = table)
> 2
Join an existing room or create a new one? type 'join' to join an existing room or the name of a room to create a new one
> Awesome
Number of players to wait for before starting the table?
> 5

This will create a table named ‘Awesome’ that will start once 5 people have joined

To join an existing table the process goes like this:

Tournament or table? (1 = tournament, 2 = table)
> 2
Join an existing room or create a new one? type 'join' to join an existing room or the name of a room to create a new one
> join
Table 1: Awesome Blinds 1 Min Players 5
Join which table?
> 1

The bot will now join that table and wait for the table to start.

Creating and joining a tournament

A PokerMatic tournament allows you to run a multi-table tournament with many bots competing against each other. The tournament
code will take care of splitting players into tables of 10, rebalancing tables as players are eliminated, and also keep track
of blind increases over time. Each player starts with 5000 chips. The tournament is over when only one bot remains!

To create a tournament, you need to use the admin tool. The admin tool will use the SPIRE_EMAIL and SPIRE_PASSWORD from your
config.rb file, so make sure those values match the values that the server is using.

The easiest way to use it is from IRB.

$> bin/admin
Tournament name?
> Awesome Tournament
1: Wed Feb 01 17:20:00 -0800 2012
2: Wed Feb 01 17:21:00 -0800 2012
3: Wed Feb 01 17:22:00 -0800 2012
4: Wed Feb 01 17:23:00 -0800 2012
5: Wed Feb 01 17:24:00 -0800 2012
6: Wed Feb 01 17:25:00 -0800 2012
7: Wed Feb 01 17:30:00 -0800 2012
8: Wed Feb 01 17:35:00 -0800 2012
9: Wed Feb 01 17:40:00 -0800 2012
10: Wed Feb 01 17:45:00 -0800 2012
11: Wed Feb 01 17:50:00 -0800 2012
12: Wed Feb 01 18:50:00 -0800 2012
13: Wed Feb 01 19:50:00 -0800 2012
14: Wed Feb 01 20:50:00 -0800 2012
15: Wed Feb 01 21:50:00 -0800 2012
Time?
> 3
Starting Blinds?
> 25
Increase blinds every how many seconds?
> 600

This will create a tournament that starts at 5:22 PM with blinds starting at 25 and increasing every 10 minutes.

To join the tournament with a bot:

Tournament or table? (1 = tournament, 2 = table)
> 1
Tourney 1: Awesome Tournament Starting at Wed Feb 01 17:22:00 -0800 2012
Join which tourney?
> 1

The bot will automatically be assigned to a table when the tournament starts.

Creating a client (bot)

PokerMatic comes with a base class (PokerClientBase) that you can extend to create your own poker bots. Bots are
placed in the /bots folder. Included are a few example bots to give you an idea of how a bot works. Also included is a
human_client, which is not really a bot but rather is a CLI client that asks a human for each move; you can use it to actually
play poker (albeit with a poor user interface).

When subclassing PokerClientBase, there is only one method that MUST be defined: ask_for_move, which receives
a GameState object when it is called. This function should return the move the client wants to take; valid moves are
‘fold’, ‘call’, ‘check’, or an amount to bet. Note that all of these moves are not available at all times; you cannot check
if a bet has already occurred, of course. A list of available moves is accessible by calling #available_moves on the GameState
object (this will be explained in more detail below).

For your bot to be included as an available bot when running bin/bot or bin/bot_cluster, just make sure the .rb file is in
the /bots directory and contains at least one class that is a subclass of PokerClientBase. If you do this, it will automatically
be included as a bot option.

GameState

The GameState object that is passed to ask_for_move contains all of the information about the current hand being played
and all of the players at the table. It includes both a ruby representation of the JSON object that the poker server
sends after each play at the table, as well as the pocket cards that the client has.

The information stored in a GameState object can be retrieved by either method call or hash.
For example, to access the current hand number, both of these will work:

game_state.hand_number
game_state[‘hand_number’]

Here is a list of all available attributes that the GameState object contains:

hand

An array of the client’s two pocket cards. For example:

[{"name"=>5, “suit”=>"Club", “value”=>5, “string”=>"5 of Clubs"},
{"name"=>"King", “suit”=>"Heart", “value”=>13, “string”=>"King of Hearts"}]

hand_number

The current hand number. Starts at 1, each hand delt at a table increases this by one.

button

The current position of the button (dealer) at the table. Corresponds to the position in
the ‘players’ array (0 indexed).

players

An array of hashes describing the players at the table. For example:

[{"name"=>"Daniel", “bankroll”=>506, “id”=>1804618},
{"name"=>"Rando", “bankroll”=>494, “id”=>1804619}]

acting_seat

The index of the currently acting player in the players array.

last_five_moves

An array of (up to) the last 5 moves of the hand. The most recent action is the last in the array.
For example:

[
{"player"=>1804618, “action”=>"raise", “bet_amount”=>3, “current_total_bet”=>4, “pot”=>6},
{"player"=>1804619, “action”=>"raise", “bet_amount”=>4, “current_total_bet”=>6, “pot”=>10},
{"player"=>1804618, “action”=>"call", “bet_amount”=>2, “current_total_bet”=>6, “pot”=>12}
]

current_bet

The total of the current bet. This is the per player bet, not the total for the round.

minimum_bet

The minimum bet a player can make.

player_bets

A hash of all the total bet each player has made in the current round, indexed by a string version
of the player id. For example:

{"1804618"=> 6, “1804619” => 8}

available_moves

A hash of all the available moves a player has given the current state of the board and the players
bankroll. The key is the name of the move and the value is the cost to the player to take that move. For example:

{"fold"=>0, “bet”=>2, “all_in”=>494, “check”=>0}

The value for bet is the MINIMUM bet, but the bet can be anywhere between this value and the all_in value.

round_history

A complete history of the betting in the current round (pre-flop, flop, etc) in the same format as last_five_moves. The most recent
action is last.

phase_name

Name of the current phase. Possible values are ‘New Hand’, ‘Pre-Flop’, ‘Flop’, ‘Turn’, ‘River’

phase

A numeric representation of the current phase. Values are:

0 – New Hand
1 – Pre-Flop
2 – Flop
3 – Turn
4 – River

players_waiting_to_join

A list of all players who wish to join the table. If a player has money in their bankroll,
they will join the game at the start of the next hand. This is also where players are placed after running
out of money.

all_in

An array of any players who are all in for the hand. Each element of the array is a hash describing the player as
well as the size of the pot they are eligible for (due to side pots). For example:

[
{"player"=>{"name"=>"Rando", “bankroll”=>0, “id”=>1804619}, “pot”=>600},
{"player"=>{"name"=>"Daniel", “bankroll”=>0, “id”=>1804618}, “pot”=>1000}
]

board

An array describing the community cards. Depending on the phase of the game, this will be either 0,3,4 or 5 cards. For example:

[
{"name"=>5, “suit”=>"Spade", “value”=>5, “string”=>"5 of Spades"},
{"name"=>"King", “suit”=>"Spade", “value”=>13, “string”=>"King of Spades"},
{"name"=>"Jack", “suit”=>"Diamond", “value”=>11, “string”=>"Jack of Diamonds"}
]

pot

The current size of the pot

players_in_hand

An array of the ids of players who are still in the hand (not folded).

acting_player

A hash describing the acting player. For example:

{"name"=>"Daniel", “bankroll”=>494, “id”=>1804618}