Click here to Skip to main content
15,887,267 members
Articles / Programming Languages / C#
Article

Poker Card Library and Poker Bot Challenge

Rate me:
Please Sign up or sign in to vote.
4.57/5 (18 votes)
8 Nov 20048 min read 230.9K   4.2K   57   122
An article on poker bots and card libraries

Introduction

A few weeks ago I read the article “Are poker ‘bots’ raking online pots?” on MSNBC’s website. Being an avid poker player/enthusiast I started toying with the idea of writing a Texas Hold’em bot just for the fun of it (ya, I know, geek). Although it seemed like a great idea at the time my enthusiasm for actually writing it wasn’t too high. Then I came across the article “Poker Bots: How Bad of a Problem are they?” that stated that “many computer programmers are going to try and fail in developing their poker bots.” Sadly, I took this as a personal affront and decided to write the bot.

However, with a slight twist. I am not trying to have my bot play in any online games or anything. I just want to see how it will do against bots created by other programmers. After enlisting several of my co-workers to write bots I started looking for other people to enter and thought that Code Project was a great place to start. So, I am posting this article in an attempt to get some of you programmers out there involved in our little tournament.

In this article I will go over the PlayingCardLibrary that I built to implement the cards and the evaluations of hands. As well as, the requirements for anyone wanting to submit a bot into the tournament. Not wanting to re-invent the wheel I decided to look around and see what was already out there. During my browsing around I found several libraries that were used to evaluate hands and implement the cards but I didn’t care for them. They often seemed long and confusing, so I decided to write my own.

The PlayingCardLibrary is a library that implements your standard 52 card deck. Ace of Spades, down to the 2 of clubs. It has 4 classes of relevance. Card.cs, Deck.cs, Hand.cs, and PokerGame5Cards.cs.

Understanding the Library

Card.cs,of course, represents the basic card in a 52 card deck. It has a member (rank) and a suit with properties to access that information. Card also has a public method that can be used to get the image of the card in JPG format.

C#
public Image CardImage()
{
  return (new CardImages.ImageRetrival()).GetImage(cardValue);
}

Card.cs implements IComparable which allows the cards to be sorted in two ways. If sortWithSuit is set to true, then the sorting will be done with regards to suit first, then rank, meaning that if you placed all the cards in an ArrayList and called its sort method the cards would be arranged exactly like a new deck of cards: Ace of Spades down to the Two of Spades, then hearts, diamonds and clubs. If sortWithSuit is false, then the cards are sorted Ace’s, King’s, Queen’s, Jack’s, …, 3’s, 2’s.

Deck.cs is your basic 52 card deck. It has three public methods of interest, Shuffle, which randomizes the cards in the deck. Resets the deckIndex to zero so new cards are dealt from the top of the deck (figuratively).

C#
public void Shuffle()
{
  // reset the index into the newly shuffled cards
  deckIndex = 0;

  // temp variable need to do the swaping
  int temp = 0;
  Card card;

  // for every card in the deck switch it with another
  for(int i = 0; i < cards.Length; i++)
  {
    temp = random.Next(0,cards.Length);
    card = cards[temp];
    cards[temp] = cards[i];
    cards[i] = card;
  }
}

The HasNext() and DealNext() methods work in conjunction. HasNext() indicates if there is another card that can be dealt and DealNext() deals that card. Calling DealNext() without checking HasNext() can lead to an IndexOutOfRangeException which is changed into a OutOfCardsException.

PokerGames5Cards.cs is where things get a little more interesting. After searching for an existing library that could evaluate a set of cards to determine the best possible 5 card (Hand) set, I found that most of the existing code was more complicated then it needed to be, often consisting of several hundred lines of code that was confusing to use. After a few hours of searching and examining existing packages I decided to write this library. Central to this library is the evaluation method. PokerGames5Cards.cs has only one public method: Evaluate, it takes a Card[] array of 5 or more cards and an object, it returns the best 5 card hand. The basic idea behind Evaluate is that it makes every possible 5 card combination and then sorts them based on the relative strength of the hand.

C#
public Hand Evaluate(Card[] cards, object player)
{
  if(cards.Length < 5)
  {
    throw new ArgumentException("Not enough Cards to perform evaluation");
  }
      
  ArrayList combinations = new ArrayList();
  int len = cards.Length;

  // iterate through all possible combinations
  for(int i = 0; i < len - 4; i++)
    for(int j = i+1; j < len - 3; j++)
      for(int k = j+1; k < len - 2; k++)
        for(int r = k+1; r < len - 1; r++)
          for(int s = r+1; s < len; s++)
          {
            // create a new hand
            Hand h = new Hand(player);
            // add  the cards
            h.AddCards(new Card[]{cards[i],
                cards[j],
                cards[k],
                cards[r],
                cards[s]});
            // evaluate the hand
            EvaluateHand(h); 
            // add it to the group
            combinations.Add(h);
          }
  // sort the compiled hands
  combinations.Sort(); 
  
  // return the largest
  return (Hand)combinations[0];
}

The code needed to determine if a hand falls with in a certain category (flush, straight, …) is fairly straight forward and I’ll leave it up to the readers to examine the code directly. The interesting part is how we evaluate each hand. Because poker hands neatly partition themselves into categories and each category can be further partitioned into subcategories, I decided to map all possible hands into the set of integers. With this accomplished, any hand can be quickly and easily compared to any other hand, without having to go into all the checks (to see if they are both 2 pairs, then checking the pairs, then checking the kickers if needed) so prominent in other packages.

I start by evaluating each hand to determine what major category it falls into (Flush, straight, …), then I reorder the cards with the strongest cards relative to the major category in the front. (The reordering isn’t really necessary but it makes it easier to put on screen if they are already in order).

Example one: (AH) = (rank, suit) = Ace of Hearts
3H, 5H, JH, 8H 2H falls into the major category for flushes. The cards are then reordered to JH, 8H, 5H, 3H, 2H and mapped into a 32 bit integer using the following private method.

C#
private int SetHandValue()
{
  int handValue = 0;
      
  handValue = ApplyMask(handValue, (int) type, 20);
  handValue = ApplyMask(handValue, (int) cards[0].GetMember, 16);
  handValue = ApplyMask(handValue, (int) cards[1].GetMember, 12);
  handValue = ApplyMask(handValue, (int) cards[2].GetMember, 8);
  handValue = ApplyMask(handValue, (int) cards[3].GetMember, 4);      
  handValue = ApplyMask(handValue, (int) cards[4].GetMember, 0);

  return handValue;
}
C#
private int ApplyMask(int origninal, int value, int shift)
{
  int temp = value << shift;
  return origninal | temp;
}

Where type is of Type enumeration

C#
private enum Type
{
  HighCard = 0,
  Pair,
  TwoPair,
  ThreeOfAKind,
  Straight,
  Flush,
  FullHouse,
  FourOfAKind,
  StraightFlush,
  RoyalFlush
}

Example two:(already reordered)
(Hand 1)8H, 8D, 2H, 2D, KC = 0010 1000 1000 0010 0010 1101
(Hand 2)8S, 8C, 2S, 2C, AC = 0010 1000 1000 0010 0010 1110
now we can see that Hand 2 easily beats Hand 1 simply by checking it numerical value.

Hand.cs is relatively simple, it is a place to hold the Card[] for each hand, the numerical value of the hand, and implements the IComparable interface so the hands can be compared against other hands.

In Summary, all of the classes in this library are short and to the point. Hands are easily partitioned possible into groups and subgroups (including kicker cards) that can be mapped directly to the set of integers for easy comparison.

BOT CHALLENGE 2K5 !!

Ok, so the fun stuff.... who is programmer enough to compete? On too, THE PROGRAMMERS CHALLENGE!!! I have written a little Texas Hold’em game. And I’d like to have as many people as possible submit their idea of a great poker bot. In January 05 we’ll have a series (around 1000) of tournaments to determine the winning bot. The reason for having more then one tournament is to give the bots a chance to learn the moves of the other bots (if desired), rather then to just rely on the statistics of the current hand, if they want to.

What your bot must do

Please Examine the second zip file. It contains all the files that you need in order to complete your bot. Of course, you need the card library along with: AbstractPlayer.cs, HoldemPlayer.cs, HoldemGameState.cs, HoldemActionEvent.cs, ActivePlayer.cs.

AbstractPlayer.cs and HoldemPlayer.cs are to abstract classes that provide a lot of the basic functionality of the player. Your bot must extend HoldemPlayer.cs, inside the holdem player you have the following information. Card[] cards contains your hole cards, you can check isButton, isBigBlind, isSmallBlind to determine if you are the dealer or one of blinds. Your inheriting class must provide concrete implementation for the abstract methods in HoldemPlayer and AbstractPlayer. That is, you must provide the functionality for the following methods:

C#
public override HoldemActionEvent 
  EvaluateCurrentAction(HoldemGameState state)
{
  // Add your code here
}

In EvaluateCurrentAction you need to make some kind of move, you are passed the current game state, which gives you PlayersChipCount (returns the players chip count), AmountNeededToCall (returns the amounted needed to call), GetPlayerList (returns a list of the active players), GetCommunityCards (returns the table cards), GetBigBlind (tells you what the current bigBlind is), GetPotSize (tells you the current size of the pot) and GetLastAction (returns the last action that was performed)

C#
public override void HoldemActionUpdate(HoldemActionEvent action)
{
  // your code here
  
}

ActionUpdate is a curtsy method that informs all the plays of moves that are made, as they are made, including your moves. They can be used to track the game. Then when you get the game state in EvaluateCurrentAction you can verify your internal tracking.

C#
public override void HoldemActionUpdate(HoldemActionEvent action)
{
  // your code here
  
}

HoldemActionUpdate gives you access to the event of the player. Specifically, the methods Actions and Amount. Actions returns the event action and Amount returns the amount associated with that action. where Actions is the following enumeration.

C#
public enum Actions
{
  FOLD = 1, 
  CALL, 
  RAISE, 
  ALLIN
}

OK, so, if you up for the action, email your bots (as text only - no attachments) to the BotChallenge2k5@hotmail.com with the following subject line: "BOT CHALLENGE 2K5 !!" and the winner will be posted after the tournaments have been run... Good programming and Good luck. These emails will be read in as text and placed into a single file named after whatever you call your class that extend HoldemPlayer.cs. so please be sure that all of the classes that you need are all working properly... No extra text, if it doesn't compile, its deleted.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: Online Poker Room Interaction Pin
jtravers8830-Apr-05 4:50
jtravers8830-Apr-05 4:50 
GeneralRe: Online Poker Room Interaction Pin
Utopius1-May-05 1:44
Utopius1-May-05 1:44 
GeneralRe: Online Poker Room Interaction Pin
jtravers881-May-05 6:16
jtravers881-May-05 6:16 
GeneralRe: Online Poker Room Interaction Pin
Utopius2-May-05 13:29
Utopius2-May-05 13:29 
GeneralRe: Online Poker Room Interaction Pin
jtravers882-May-05 16:59
jtravers882-May-05 16:59 
GeneralRe: Online Poker Room Interaction Pin
a poker wiz5-Jun-05 3:13
sussa poker wiz5-Jun-05 3:13 
GeneralRe: Online Poker Room Interaction Pin
Anonymous5-Sep-05 18:29
Anonymous5-Sep-05 18:29 
QuestionPoker Challenge 2005? Pin
Utopius14-Apr-05 14:29
Utopius14-Apr-05 14:29 
I'd like to commit to completing this poker challenge and sustaining the effort that Wesman initiated. I have underestimated the amount of work required to get this type of tournament off the ground, but I certainly believe it is well worth the effort...a truly great learning opportunity.

Since Wesman declared the competition requirements, I was deeply convinced that I would not be able to produce a high-calbre bot algorithm without a well tested, adn available server to test my design against. Consquently, I decided to pursue the development of poker gaming server (C# with .NET Remoting). Now, 5 months after the contest was declared, I believe I am onlyh weeks away from launching version #2 of my game server. However, I need to work with each of you in terms of what kind of information our bots should have access to, and how to make all this effort worthwhile to everyone. Any feedback would be greatly appreciated.

In addition to the game engine, business entities, interfaces, and Windows-Client interface, I've completed a great deal of work in my pursuit to continue this effort. Wesman kickstarted the effort by providing an efficient and elegant way to evaluate the strength of a given 5-card poker hand, and with his recent family crisis, I can only hope to honour him by continuing where he left off.

To this end, I've have built an entire infrastructure on the .NET Framework that supports the following features:

- support for human players and automated bot players
- support for Texas Holdem: limits, potLimits, and noLimits
- extensibility to support other game variations such as Omaha-High

If I understand Wesman's original vision, here's what I'd like to see happening on a weekly basis (at first):

- weekly tournaments for each of 3 tables: Limits, PotLimits, NoLimits
- players can play as humans (discouraged), or can develop their own Bots to playe each week
- bots should have a useful (but limited) framework library to perform a variety of tasks such as:
- evaluate the strength of 2-card hand
- evaluate the strength of a 5 card-hand (as Wesman demonstrated)
- evaluate the probability of obtaining a target hand (i.e. Flush draw...etc)
- most importantly, should be able to model their opponents behavior WRT bluffing!

To this end, I have defined the following interface for bot developers. The interface is still under construction, but it is nearly solidifed...if you have commenets or suggestions on how to improve it, I will gladly make the necessary changes. So here goes...

/////////////////////////////////////////////////////////////////////////////////////////////
///
/// Assumptions for Bot Developers
/// 1. Oppenents can be modeled based on their seatIndex,
/// which is assumed to remained constant throughout the tournament for this table.
/// 2. Opponent modeling will be limited to this particular tournament.
///

public interface IBot
{

// can extract playerInfo (if interested) and reset
void ResetForNextHand( TableInfo tableInfo );

// can obtain an update on the pot at end of each betting round
void ResetForNextRound( float pot );

// this is an ABSOLUTE update (3 cards, then 4 cards, then 5 cards)
void DealCommunityCards(CardInfo[] cardArray);

// these are your private hole cards
void DealHoleCards(CardInfo[] cardArray);

// this is the most important method - all bots must at least implement something here
ActionChoice DoAction( ActionOptions actionOptions );

// this is the most common action update - occurs each time a player take any action
// (i.e. decides to FOLD, CALL, or RAISE)
void PlayerActionUpdate( int seatIndex, ActionOption lastAction, float credit, float wager, float newPot );

// this server update occurs at the end of each hand - the winner is declared
// bot developers can use this update to determine if a given oppenent has a tendancy to bluff
void DeclareWinner( CardInfo[][] activePlayerHoleCardsArray, float pot, int winnerSeatIndex,
string userName, string winHandType, string winHandString );
/////////////////////////////////////////////////////////////////////////////////////////////

So, as Wesman formulated, the DoAction() method is really where the Bot needs to provide a solid implementation based on the list of ActionOption items. There is always a FOLD and CHEKC/CALL type options, but BET/RAISE options may be available as well (otherwise NULL). The bot developer can go well beyond just implementing code for this method and in fact analyze the holeCards he has been dealth, as well as the communityCards dealt to the Table. Advanced bots can attempt to model their opponents through the PlayerActionUpdate() method which is posted to all bots/players with each action made (i.e. FOLD, BET...etc).

I won't give a complete explanation of help documentation at this point because I'd like to hear what you guys think. I this the type of tournament you were envisioning? Is there sufficient server updates to allow you to develop a highly capable (and hopefully successful) bot? What's missing? What needs to be added? Or what don't you understand at this point?...perhaps this interface is a bit confusing?

Let me know your thoughts...I'll be back in 2 weeks to review your results before tackling the last phase of development of my second version of this exciting poker application. If we can agree on the application constraints, I'm certain I can launch a quick and dirty website with detailed instructions on how to download the PokerBot-SDK and provide some sample bot implementations as well as NDoc class library documentation within the next 4-8 weeks. Please provide feedback (positive or negative)...my initial testing shows that I have (at the very least) a solid architecture in place and stable design upon which I can extend.

Let me know if you're still interested...I'd be happy to post the MSI download for the WindowsClient I built that you can use to watch the game at a particular table, physically play the game as a human player, or watch your bot play against its opponents in real time.

Unfortunately, I do plan to host this server from my home machine which limits the number of tables I will be able to support, but perhaps those most interested can come forward to participate in the first round of tournaments (4-8weeks from now).

Feedback is highly encouraged...thanks for your patience and support.
Big Grin | :-D

Utopius
AnswerRe: Poker Challenge 2005? Pin
hipsvin19-Apr-05 0:23
hipsvin19-Apr-05 0:23 
GeneralRe: Poker Challenge 2005? Pin
Utopius2-May-05 14:10
Utopius2-May-05 14:10 
AnswerRe: Poker Challenge 2005? Pin
csshelton7027-Apr-05 6:41
csshelton7027-Apr-05 6:41 
GeneralRe: Poker Challenge 2005? Pin
Utopius2-May-05 14:09
Utopius2-May-05 14:09 
AnswerRe: Poker Challenge 2005? Pin
netclectic28-Apr-05 2:44
netclectic28-Apr-05 2:44 
AnswerRe: Poker Challenge 2005? Pin
Utopius30-Apr-05 2:26
Utopius30-Apr-05 2:26 
GeneralContinuance of this Challenge Pin
aprenot26-Feb-05 9:12
aprenot26-Feb-05 9:12 
GeneralRe: Continuance of this Challenge Pin
netclectic21-Mar-05 2:15
netclectic21-Mar-05 2:15 
GeneralRe: Continuance of this Challenge Pin
aprenot21-Mar-05 5:36
aprenot21-Mar-05 5:36 
GeneralRe: Continuance of this Challenge Pin
netclectic21-Mar-05 6:05
netclectic21-Mar-05 6:05 
GeneralRe: Continuance of this Challenge Pin
Adonai0x4227-Mar-05 8:23
Adonai0x4227-Mar-05 8:23 
GeneralRe: Continuance of this Challenge Pin
csshelton701-Apr-05 9:42
csshelton701-Apr-05 9:42 
GeneralRe: Continuance of this Challenge Pin
Utopius13-Apr-05 3:40
Utopius13-Apr-05 3:40 
GeneralBad News Pin
wesman16-Feb-05 5:50
wesman16-Feb-05 5:50 
GeneralRe: Bad News Pin
Utopius12-May-05 14:12
Utopius12-May-05 14:12 
GeneralRe: Bad News Pin
wesman12-May-05 14:49
wesman12-May-05 14:49 
GeneralInterested Reader... Pin
KelsoTheMan5-Feb-05 11:46
KelsoTheMan5-Feb-05 11:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.