package pokercore func (c Cards) scoreStraightFlush() HandScore { if !c.containsStraightFlush() { panic("hand must be a straight flush to score it") } return ScoreStraightFlush + 1000*c.HighestRank().Score() } func (c Cards) scoreFlush() HandScore { if !c.containsFlush() { panic("hand must be a flush to score it") } var score HandScore for _, card := range c { score += card.Rank.Score() } return ScoreFlush + score } func (c Cards) scoreHighCard() HandScore { if !c.isUnmadeHand() { panic("hand must be a high card to score it") } var score HandScore for _, card := range c { score += card.Rank.Score() } return ScoreHighCard + score } func (c Cards) pairRank() Rank { if !c.containsPair() { panic("hand must have a pair to have a pair rank") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank { return sorted[0].Rank } if sorted[1].Rank == sorted[2].Rank { return sorted[1].Rank } if sorted[2].Rank == sorted[3].Rank { return sorted[2].Rank } if sorted[3].Rank == sorted[4].Rank { return sorted[3].Rank } panic("nope") } func (c Cards) pairFirstKicker() Card { if !c.containsPair() { panic("hand must have a pair to have a first kicker") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank { return sorted[4] } if sorted[1].Rank == sorted[2].Rank { return sorted[4] } if sorted[2].Rank == sorted[3].Rank { return sorted[4] } if sorted[3].Rank == sorted[4].Rank { return sorted[2] } panic("nope") } func (c Cards) pairSecondKicker() Card { if !c.containsPair() { panic("hand must have a pair to have a second kicker") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank { // first kicker is [4] return sorted[3] } if sorted[1].Rank == sorted[2].Rank { // first kicker is [4] return sorted[3] } if sorted[2].Rank == sorted[3].Rank { // first kicker is [4] return sorted[1] } if sorted[3].Rank == sorted[4].Rank { // first kicker is [2] return sorted[1] } panic("nope") } func (c Cards) pairThirdKicker() Card { if !c.containsPair() { panic("hand must have a pair to have a third kicker") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank { // first kicker is [4] // second kicker is [3] return sorted[2] } if sorted[1].Rank == sorted[2].Rank { // first kicker is [4] // second kicker is [3] return sorted[0] } if sorted[2].Rank == sorted[3].Rank { // first kicker is [4] // second kicker is [1] return sorted[0] } if sorted[3].Rank == sorted[4].Rank { // first kicker is [2] // second kicker is [1] return sorted[0] } panic("nope") } func (c Cards) twoPairBiggestPair() Rank { if !c.containsTwoPair() { panic("hand must have two pair to have a biggest pair") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank { return sorted[2].Rank } if sorted[0].Rank == sorted[1].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[0].Rank } if sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[1].Rank } panic("nope") } func (c Cards) twoPairSmallestPair() Rank { if !c.containsTwoPair() { panic("hand must have two pair to have a smallest pair") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank { return sorted[2].Rank } if sorted[0].Rank == sorted[1].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[3].Rank } if sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[3].Rank } panic("nope") } func (c Cards) twoPairKicker() Card { if !c.containsTwoPair() { panic("hand must have two pair to have a twoPairKicker") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank { return sorted[4] } if sorted[0].Rank == sorted[1].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[2] } if sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[0] } panic("nope") } func (c Cards) threeOfAKindTripsRank() Rank { if !c.containsThreeOfAKind() { panic("hand must have three of a kind to have a trips rank") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank { return sorted[0].Rank } if sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank { return sorted[1].Rank } if sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[2].Rank } panic("nope") } func (c Cards) threeOfAKindKickers() Cards { if !c.containsThreeOfAKind() { panic("hand must have three of a kind to have kickers") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank { return Cards{sorted[3], sorted[4]} } if sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank { return Cards{sorted[0], sorted[4]} } if sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return Cards{sorted[0], sorted[1]} } panic("nope") } func (c Cards) threeOfAKindFirstKicker() Card { x := c.threeOfAKindKickers() return x[0] } func (c Cards) threeOfAKindSecondKicker() Card { x := c.threeOfAKindKickers() return x[1] } func (c Cards) fourOfAKindRank() Rank { if !c.containsFourOfAKind() { panic("hand must have four of a kind to have a four of a kind rank") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank { return sorted[0].Rank } if sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[1].Rank } panic("nope") } func (c Cards) fourOfAKindKicker() Card { if !c.containsFourOfAKind() { panic("hand must have four of a kind to have a four of a kind kicker") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank { return sorted[4] } if sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[0] } panic("nope") } func (c Cards) fullHouseTripsRank() Rank { if !c.containsFullHouse() { panic("hand must have a full house to have a trips rank") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[0].Rank } if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[4].Rank } panic("nope") } func (c Cards) fullHousePairRank() Rank { if !c.containsFullHouse() { panic("hand must have a full house to have a pair rank") } sorted := c.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[4].Rank } if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return sorted[0].Rank } panic("nope") } func (hand Cards) containsDuplicates() bool { seen := make(map[Card]bool) for _, card := range hand { if _, ok := seen[card]; ok { return true } seen[card] = true } return false } func (hand Cards) IsFiveCardPokerHand() bool { return len(hand) == 5 && !hand.containsDuplicates() } func (hand Cards) containsFlush() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } suit := hand[0].Suit for i := 1; i < len(hand); i++ { if hand[i].Suit != suit { return false } } return true } func (hand Cards) containsStraight() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } sorted := hand.SortByRankAscending() if sorted[4].Rank == ACE && sorted[3].Rank == FIVE { // special case for A-5 straight if sorted[0].Rank == DEUCE && sorted[1].Rank == THREE && sorted[2].Rank == FOUR { return true } else { return false } } return sorted[0].Rank.Int()+1 == sorted[1].Rank.Int() && sorted[1].Rank.Int()+1 == sorted[2].Rank.Int() && sorted[2].Rank.Int()+1 == sorted[3].Rank.Int() && sorted[3].Rank.Int()+1 == sorted[4].Rank.Int() } func (hand Cards) containsStraightFlush() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } if hand.containsStraight() && hand.containsFlush() { return true } return false } func (hand Cards) containsRoyalFlush() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } // This seems like it works, but a five-high straight flush is not a royal flush // and the highest ranked card in five-high straigh flush is an ace. //if hand.containsStraightFlush() && hand.HighestRank() == ACE { // return true //} sorted := hand.SortByRankAscending() if hand.containsStraightFlush() && hand.HighestRank() == ACE && sorted[0].Rank == TEN { return true } return false } func (hand Cards) containsFourOfAKind() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } sorted := hand.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank { // the quads precede the kicker return true } if sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { // the kicker is the first card return true } return false } func (hand Cards) containsFullHouse() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } sorted := hand.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { // the trips precede the pair return true } if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { // the pair is first return true } return false } func (hand Cards) containsPair() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } sorted := hand.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank { return true } if sorted[1].Rank == sorted[2].Rank { return true } if sorted[2].Rank == sorted[3].Rank { return true } if sorted[3].Rank == sorted[4].Rank { return true } return false } func (hand Cards) containsThreeOfAKind() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } sorted := hand.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[1].Rank == sorted[2].Rank { return true } if sorted[1].Rank == sorted[2].Rank && sorted[2].Rank == sorted[3].Rank { return true } if sorted[2].Rank == sorted[3].Rank && sorted[3].Rank == sorted[4].Rank { return true } return false } func (hand Cards) containsTwoPair() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } sorted := hand.SortByRankAscending() if sorted[0].Rank == sorted[1].Rank && sorted[2].Rank == sorted[3].Rank { return true } if sorted[0].Rank == sorted[1].Rank && sorted[3].Rank == sorted[4].Rank { return true } if sorted[1].Rank == sorted[2].Rank && sorted[3].Rank == sorted[4].Rank { return true } return false } func (hand Cards) isUnmadeHand() bool { if !hand.IsFiveCardPokerHand() { panic("hand must have 5 cards to be scored") } return !hand.containsPair() && !hand.containsTwoPair() && !hand.containsThreeOfAKind() && !hand.containsStraight() && !hand.containsFlush() && !hand.containsFullHouse() && !hand.containsFourOfAKind() && !hand.containsStraightFlush() && !hand.containsRoyalFlush() }