Tuesday, May 30, 2006

 
Calculating Outs (Part 1)

Most Hold'em players know what Outs are. According to Wikipedia an out is:

[A]n out is any unseen card that, if drawn, will improve a player's hand to one that is likely to win

The question for the programmer is, is this definition sufficent to write a function that returns the cards that are outs?

Let's look at the two key points made by Wikipedia. They are:

  1. The hand must improve
  2. The new hand is likely to win.

Let's start by writing a function that meets the first criterion.



using System;
using HoldemHand;

// A first try at calculating outs
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string pocket = "As Ac";
string board = "Kd 8h 9c";
// Calcuate the outs
ulong outsmask = Outs(Hand.ParseHand(pocket), Hand.ParseHand(board));

Console.WriteLine("[{0}] {1} : Outs Count {2}",
pocket, board, Hand.BitCount(outsmask));

// List the cards
foreach (string card in Hand.Cards(outsmask))
{
Console.Write("{0} ", card);
}
Console.WriteLine();
}

// Return a hand mask of the cards that improve our hand
static ulong Outs(ulong pocket, ulong board)
{
ulong retval = 0UL;
ulong hand = pocket board;

// Get original hand value
uint playerOrigHandVal = Hand.Evaluate(hand);

// Look ahead one card
foreach (ulong card in Hand.Hands(0UL, hand, 1))
{
// Get new hand value
uint playerNewHandVal = Hand.Evaluate(hand card);

// If the hand improved then we have an out
if (playerNewHandVal > playerOrigHandVal)
{
// Add card to outs mask
retval = card;
}
}

// return outs as a hand mask
return retval;
}
}
}




Passing this starting hand A♠ A♣, K♦ 8♥ 9♣ it into our new method returns the following outs:

  1. K♠, 9♠, 9♥, 8♠, K♥, 9♦, 8♦, K♣, 8♣ - Two pair
  2. A♥, A♦ - Trips
  3. Q♠, J♠, T♠, Q♥, J♥, T♥, Q♦, J♦, T♦, Q♣, J♣, T♣ - Improves Kicker

I think most people would agree that super-sizing your kicker probably doesn't help much here. I think most people would also agree that improving the board doesn't help either. So let's add two more rules:

  1. The hand must improve
  2. The new hand improvement must be better than an improved kicker
  3. The new combined hand must be stronger than the just the board
  4. The new hand is likely to win

The following example handle these new rules and allows opponent hands to be added.





using System;
using HoldemHand;

// A first try at calculating outs
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string pocket = "As Ac";
string board = "Kd 8h 9c";
// Calcuate the outs
ulong outsmask = Outs(Hand.ParseHand(pocket), Hand.ParseHand(board));

Console.WriteLine("[{0}] {1} : Outs Count {2}",
pocket, board, Hand.BitCount(outsmask));

// List the cards
foreach (string card in Hand.Cards(outsmask))
{
Console.Write("{0} ", card);
}
Console.WriteLine();
}

// Return a hand mask of the cards that improve our hand
static ulong Outs(ulong pocket, ulong board, params ulong [] opponents)
{
ulong retval = 0UL;

// Get original hand value
uint playerOrigHandVal = Hand.Evaluate(pocket board);

// Look ahead one card
foreach (ulong card in Hand.Hands(0UL, board pocket, 1))
{
// Get new hand value
uint playerNewHandVal = Hand.Evaluate(pocket board card);

// Get new board value
uint boardHandVal = Hand.Evaluate(board card);

// Is the new hand better than the old one?
bool handImproved = playerNewHandVal > playerOrigHandVal &&
Hand.HandType(playerNewHandVal) > Hand.HandType(playerOrigHandVal);

// This compare ensures we move up in hand type.
bool handStrongerThanBoard =
Hand.HandType(playerNewHandVal) > Hand.HandType(boardHandVal);

// Check against opponents cards
bool handBeatAllOpponents = true;
if (handImproved && handStrongerThanBoard &&
opponents != null && opponents.Length > 0)
{
foreach (ulong opponent in opponents)
{
uint opponentHandVal = Hand.Evaluate(opponent board card);
if (opponentHandVal > playerNewHandVal)
{
handBeatAllOpponents = false;
break;
}
}
}

// If the hand improved then we have an out
if (handImproved && handStrongerThanBoard && handBeatAllOpponents)
{
// Add card to outs mask
retval = card;
}
}

// return outs as a hand mask
return retval;
}
}
}




Passing this starting hand A♠ A♣, K♦ 8♥ 9♣ to our new method produces following outs:

  1. K♠, 9♠, 9♥, 8♠, K♥, 9♦, 8♦, K♣, 8♣ - Two pair
  2. A♥, A♦ - Trips

This new method is certainly better than our first method. But we can still do better.

Stay tuned for more indepth discussion on improving our outs method.


Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?