package pokercore import ( "fmt" ) type HandScore int const ( ScoreHighCard = HandScore(iota * 100_000_000_000) ScorePair ScoreTwoPair ScoreThreeOfAKind ScoreStraight ScoreFlush ScoreFullHouse ScoreFourOfAKind ScoreStraightFlush ScoreRoyalFlush ) func (c Card) Score() HandScore { return HandScore(c.Rank.Score()) } func (c Cards) PokerHandScore() (HandScore, error) { ph, err := c.PokerHand() if err != nil { return 0, err } return ph.Score, nil } func (x HandScore) String() string { return fmt.Sprintf("", x) } func (ph *PokerHand) calculateScore() { // sanity check, we should only be called in the PokerHand() method from // a Cards, but just in case if len(ph.Hand) != 5 { // normally we don't panic in a library but this is a "should never // happen" panic("PokerHand.calculateScore() called on a PokerHand with != 5 cards") } if ph.Hand.containsRoyalFlush() { ph.Type = RoyalFlush ph.Score = ScoreRoyalFlush return } if ph.Hand.containsStraightFlush() { ph.Type = StraightFlush ph.Score = ScoreStraightFlush ph.Score += ph.Hand.HighestRank().Score() return } if ph.Hand.containsFourOfAKind() { ph.Type = FourOfAKind ph.Score = ScoreFourOfAKind ph.Score += 10000 * ph.Hand.fourOfAKindRank().Score() ph.Score += 100 * ph.Hand.fourOfAKindKicker().Score() return } if ph.Hand.containsFullHouse() { ph.Type = FullHouse ph.Score = ScoreFullHouse ph.Score += 10000 * ph.Hand.fullHouseTripsRank().Score() ph.Score += 100 * ph.Hand.fullHousePairRank().Score() return } if ph.Hand.containsFlush() { ph.Type = Flush ph.Score = ScoreFlush // flush base score plus sum of card ranks ph.Score += ph.Hand[0].Score() ph.Score += ph.Hand[1].Score() ph.Score += ph.Hand[2].Score() ph.Score += ph.Hand[3].Score() ph.Score += ph.Hand[4].Score() return } if ph.Hand.containsStraight() { ph.Type = Straight ph.Score = ScoreStraight // note that ph.Hand is already sorted by rank ascending with ace // high // Straights are scored by the highest card in the straight // UNLESS the second highest card is a 5 and the highest card is an Ace // In that case, the straight is a 5-high straight, not an Ace-high straight if ph.Hand[3].Rank == FIVE && ph.Hand[4].Rank == ACE { // 5-high straight, scored by the five's rank ph.Score += ph.Hand[3].Score() } else { // All other straights are scored by the highest card in the straight ph.Score += ph.Hand[4].Score() } return } if ph.Hand.containsThreeOfAKind() { ph.Type = ThreeOfAKind ph.Score = ScoreThreeOfAKind ph.Score += 10000 * ph.Hand.threeOfAKindTripsRank().Score() ph.Score += 100 * ph.Hand.threeOfAKindFirstKicker().Score() ph.Score += ph.Hand.threeOfAKindSecondKicker().Score() return } if ph.Hand.containsTwoPair() { ph.Type = TwoPair ph.Score = ScoreTwoPair ph.Score += 10000 * ph.Hand.twoPairBiggestPair().Score() ph.Score += 100 * ph.Hand.twoPairSmallestPair().Score() ph.Score += ph.Hand.twoPairKicker().Score() return } if ph.Hand.containsPair() { ph.Type = Pair ph.Score = ScorePair ph.Score += 10000 * ph.Hand.pairRank().Score() ph.Score += 100 * ph.Hand.pairFirstKicker().Score() ph.Score += ph.Hand.pairSecondKicker().Score() ph.Score += ph.Hand.pairThirdKicker().Score() return } ph.Type = HighCard ph.Score = ScoreHighCard // base score // unmade hands are scored like flushes, just add up the values ph.Score += ph.Hand[0].Score() ph.Score += ph.Hand[1].Score() ph.Score += ph.Hand[2].Score() ph.Score += ph.Hand[3].Score() ph.Score += ph.Hand[4].Score() }