Introduce HandRank

This commit is contained in:
Andrew Cooper
2022-06-19 23:09:02 +10:00
parent fc65452ae6
commit 7199cdbb4d
3 changed files with 71 additions and 57 deletions
+31 -51
View File
@@ -1,5 +1,5 @@
using System.Text;
using static Poker.Cards.HandRank;
namespace Poker.Cards;
internal class Hand
@@ -7,15 +7,11 @@ internal class Hand
public static readonly Hand Empty = new Hand();
private readonly Card[] _cards;
private readonly string _name1;
private readonly string _name2;
private Hand()
{
_cards = Array.Empty<Card>();
_name1 = "";
_name2 = "";
Name = "";
Rank = None;
}
public Hand(IEnumerable<Card> cards)
@@ -26,16 +22,15 @@ internal class Hand
private Hand(IEnumerable<Card> cards, bool isAfterDraw)
{
_cards = cards.ToArray();
(Rank, _name1, _name2, HighCard, KeepMask) = Analyze();
Name = GetHandName();
(Rank, HighCard, KeepMask) = Analyze();
IsWeak = Rank < 10
|| Rank == 10 && isAfterDraw
|| Rank <= 12 && HighCard.Rank <= 6;
IsWeak = Rank < PartialStraight
|| Rank == PartialStraight && isAfterDraw
|| Rank <= TwoPair && HighCard.Rank <= 6;
}
public string Name { get; }
public int Rank { get; }
public string Name => Rank.ToString(HighCard);
public HandRank Rank { get; }
public Card HighCard { get; }
public int KeepMask { get; set; }
public bool IsWeak { get; }
@@ -48,7 +43,7 @@ internal class Hand
return new Hand(_cards, isAfterDraw: true);
}
private (int, string, string, Card, int) Analyze()
private (HandRank, Card, int) Analyze()
{
var suitMatchCount = 0;
for (var i = 0; i < _cards.Length; i++)
@@ -60,31 +55,31 @@ internal class Hand
}
if (suitMatchCount == 4)
{
return (15, "A Flus", "h in", _cards[0], 0b11111);
return (Flush, _cards[0], 0b11111);
}
var sortedCards = _cards.OrderBy(c => c.Rank).ToArray();
var handRank = 0;
var handRank = Schmaltz;
var keepMask = 0;
Card highCard = default;
var handName1 = "";
var handName2 = "";
for (var i = 0; i < sortedCards.Length - 1; i++)
{
if (sortedCards[i].Rank == sortedCards[i+1].Rank)
var matchesNextCard = sortedCards[i].Rank == sortedCards[i+1].Rank;
var matchesPreviousCard = i > 0 && sortedCards[i].Rank == sortedCards[i - 1].Rank;
if (matchesNextCard)
{
keepMask |= 0b11 << i;
highCard = sortedCards[i];
(handRank, handName1, handName2) =
(handRank, i > 0 && sortedCards[i].Rank == sortedCards[i - 1].Rank) switch
{
(<11, _) => (11, "A Pair", " of "),
(11, true) => (13, "Three", " "),
(11, _) => (12, "Two P", "air, "),
(12, _) => (16, "Full H", "ouse, "),
(_, true) => (17, "Four", " "),
_ => (16, "Full H", "ouse, ")
};
handRank = matchesPreviousCard switch
{
_ when handRank < Pair => Pair,
true when handRank == Pair => Three,
_ when handRank == Pair => TwoPair,
_ when handRank == TwoPair => FullHouse,
true => Four,
_ => FullHouse
};
}
}
if (keepMask == 0)
@@ -92,36 +87,21 @@ internal class Hand
if (sortedCards[3] - sortedCards[0] == 3)
{
keepMask=0b1111;
handRank=10;
handRank=PartialStraight;
}
if (sortedCards[4] - sortedCards[1] == 3)
{
if (handRank == 10)
if (handRank == PartialStraight)
{
return (14, "Straig", "ht", sortedCards[4], 0b11111);
return (Straight, sortedCards[4], 0b11111);
}
handRank=10;
handRank=PartialStraight;
keepMask=0b11110;
}
}
return handRank < 10
? (9, "Schmal", "tz, ", sortedCards[4], 0b11000)
: (handRank, handName1, handName2, highCard, keepMask);
}
private string GetHandName()
{
var sb = new StringBuilder(_name1).Append(_name2);
if (_name1 == "A Flus")
{
sb.Append(HighCard.Suit).AppendLine();
}
else
{
sb.Append(HighCard.Rank)
.AppendLine(_name1 == "Schmal" || _name1 == "Straig" ? " High" : "'s");
}
return sb.ToString();
return handRank < PartialStraight
? (Schmaltz, sortedCards[4], 0b11000)
: (handRank, highCard, keepMask);
}
public override string ToString()
+34
View File
@@ -0,0 +1,34 @@
namespace Poker.Cards;
internal class HandRank
{
public static HandRank None = new(0, "");
public static HandRank Schmaltz = new(1, "schmaltz, ", c => $"{c.Rank} high");
public static HandRank PartialStraight = new(2, ""); // The original code does not assign a display string here
public static HandRank Pair = new(3, "a pair of ", c => $"{c.Rank}'s");
public static HandRank TwoPair = new(4, "two pair, ", c => $"{c.Rank}'s");
public static HandRank Three = new(5, "three ", c => $"{c.Rank}'s");
public static HandRank Straight = new(6, "straight", c => $"{c.Rank} high");
public static HandRank Flush = new(7, "a flush in ", c => c.Suit.ToString());
public static HandRank FullHouse = new(8, "full house, ", c => $"{c.Rank}'s");
public static HandRank Four = new(9, "four ", c => $"{c.Rank}'s");
// The original code does not detect a straight flush or royal flush
private readonly int _value;
private readonly string _displayName;
private readonly Func<Card, string> _suffixSelector;
private HandRank(int value, string displayName, Func<Card, string>? suffixSelector = null)
{
_value = value;
_displayName = displayName;
_suffixSelector = suffixSelector ?? (_ => "");
}
public string ToString(Card highCard) => $"{_displayName}{_suffixSelector.Invoke(highCard)}";
public static bool operator >(HandRank x, HandRank y) => x._value > y._value;
public static bool operator <(HandRank x, HandRank y) => x._value < y._value;
public static bool operator >=(HandRank x, HandRank y) => x._value >= y._value;
public static bool operator <=(HandRank x, HandRank y) => x._value <= y._value;
}
+6 -6
View File
@@ -59,12 +59,12 @@ internal class Game
Z = table.Computer.Hand.Rank switch
{
_ when table.Computer.Hand.IsWeak =>
table.Computer.BluffIf(Get0To9() > 7, 0b11100) ??
table.Computer.BluffIf(Get0To9() > 7, 0b11110) ??
table.Computer.BluffIf(Get0To9() < 2, 0b11100) ??
table.Computer.BluffIf(Get0To9() < 2, 0b11110) ??
table.Computer.BluffIf(Get0To9() < 1, 0b11111) ??
1,
< 13 => table.Computer.BluffIf(Get0To9() < 2) ?? 0,
<= 16 => 35,
_ when table.Computer.Hand.Rank < HandRank.Three => table.Computer.BluffIf(Get0To9() < 2) ?? 0,
_ when table.Computer.Hand.Rank < HandRank.FullHouse => 35,
_ when Get0To9() < 1 => 35,
_ => 2
};
@@ -90,8 +90,8 @@ internal class Game
{
_ when table.Computer.IsBluffing => 28,
_ when table.Computer.Hand.IsWeak => 1,
< 13 => Get0To9() == 0 ? 19 : 2,
< 16 => Get0To9() == 8 ? 11 : 19,
_ when table.Computer.Hand.Rank < HandRank.Three => Get0To9() == 0 ? 19 : 2,
_ when table.Computer.Hand.Rank < HandRank.FullHouse => Get0To9() == 0 ? 11 : 19,
_ => 2
};