package pokercore import "encoding/binary" import "fmt" import crand "crypto/rand" import . "github.com/logrusorgru/aurora" import log "github.com/sirupsen/logrus" import rand "math/rand" import "strings" type Suit rune type Rank rune const ( CLUB Suit = '\u2663' SPADE Suit = '\u2660' DIAMOND Suit = '\u2666' HEART Suit = '\u2665' ) /* // emoji are cooler anyway const CLUB = "C" const SPADE = "S" const DIAMOND = "D" const HEART = "H" */ const ( ACE Rank = 'A' DEUCE Rank = '2' THREE Rank = '3' FOUR Rank = '4' FIVE Rank = '5' SIX Rank = '6' SEVEN Rank = '7' EIGHT Rank = '8' NINE Rank = '9' TEN Rank = 'T' JACK Rank = 'J' QUEEN Rank = 'Q' KING Rank = 'K' ) type TestGenerationIteration struct { Deck *Deck Seed int64 } type Card struct { Rank Rank Suit Suit } type Cards []*Card type Deck struct { Cards Cards DealIndex int ShuffleSeedVal int64 } func formatCardsForTerminal(c Cards) (output string) { var cardstrings []string for i := 0; i < len(c); i++ { cardstrings = append(cardstrings, formatCardForTerminal(*c[i])) } output = strings.Join(cardstrings, ",") return output } func formatCardForTerminal(c Card) (output string) { var rank string var suit string color := Red switch c.Suit { case Suit(DIAMOND): color = Blue case Suit(HEART): color = Red case Suit(CLUB): color = Green case Suit(SPADE): color = Black } rank = fmt.Sprintf("%s", BgGray(Bold(color(c.Rank)))) suit = fmt.Sprintf("%s", BgGray(Bold(color(c.Suit)))) output = fmt.Sprintf("%s%s", rank, suit) return output } func cryptoUint64() (v uint64) { err := binary.Read(crand.Reader, binary.BigEndian, &v) if err != nil { log.Fatal(err) } log.Debugf("crand cryptosource is returning Uint64: %d", v) return v } func (self *Card) String() string { return fmt.Sprintf("%s%s", string(self.Rank), string(self.Suit)) } func NewDeck() *Deck { self := new(Deck) ranks := []Rank{ ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING} suits := []Suit{HEART, DIAMOND, CLUB, SPADE} self.Cards = make([]*Card, 52) tot := 0 for i := 0; i < len(ranks); i++ { for n := 0; n < len(suits); n++ { self.Cards[tot] = &Card{ Rank: ranks[i], Suit: suits[n], } tot++ } } self.DealIndex = 0 return self } func (self *Deck) ShuffleRandomly() { rnd := rand.New(rand.NewSource(int64(cryptoUint64()))) //FIXME(sneak) not sure if this is constant time or not rnd.Shuffle(len(self.Cards), func(i, j int) { self.Cards[i], self.Cards[j] = self.Cards[j], self.Cards[i] }) self.DealIndex = 0 } func (self *Deck) ShuffleDeterministically(seed int64) { r := rand.New(rand.NewSource(seed)) //FIXME(sneak) not sure if this is constant time or not r.Shuffle(len(self.Cards), func(i, j int) { self.Cards[i], self.Cards[j] = self.Cards[j], self.Cards[i] }) self.DealIndex = 0 } func (self *Deck) Deal(n int) (output Cards) { if (self.DealIndex + n) > len(self.Cards) { return output } for i := 0; i < n; i++ { output = append(output, self.Cards[self.DealIndex+1]) self.DealIndex++ } return output } func (self *Deck) Dealt() int { return self.DealIndex } func (self *Deck) Remaining() int { return (len(self.Cards) - self.DealIndex) } func (s Cards) String() (output string) { var cardstrings []string for i := 0; i < len(s); i++ { cardstrings = append(cardstrings, s[i].String()) } output = strings.Join(cardstrings, ",") return output } func generate() { log.SetLevel(log.DebugLevel) } func proto() { myDeck := NewDeck() myDeck.ShuffleDeterministically(42) myHand := myDeck.Deal(2) //spew.Dump(myHand) fmt.Printf("my hand: %s\n", myHand) cmty := myDeck.Deal(5) fmt.Printf("community: %s\n", cmty) } func scorePokerHand(input Cards) (score int) { /* scoring system: high card: high card * 14^4 + first kicker * 14^3 + second kicker * 14^2 + third kicker * 14 + fourth kicker max(AKQJ9): 576,011 single pair: pair value * 1,000,000 + first kicker * 14^2 + second kicker * 14 + third kicker max(AAKQJ): 14,002,727 two pair: higher of the two pair value * 100,000,000 + lower of the two pair value * 14 + kicker value max(AAKKQ): 1,300,000,179 trips: trips value * 1,000,000,000 (min 2,000,000,000) + first kicker * 14 + second kicker max (AAAKQ): 14,000,000,194 straight: highest card * 10,000,000,000 straight to the ace: 140,000,000,000 flush: highest card * 100,000,000,000 min(23457): 700,000,000,000 max(AXXXX): 1,400,000,000,000 boat: */ return 1 }