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" const CLUB = "\u2663" const SPADE = "\u2660" const DIAMOND = "\u2666" const HEART = "\u2665" /* const CLUB = "C" const SPADE = "S" const DIAMOND = "D" const HEART = "H" */ type TestGenerationIteration struct { Deck *Deck Seed int64 } type Card struct { Rank string Suit string } 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 DIAMOND: color = Blue case HEART: color = Red case CLUB: color = Green case 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", self.Rank, self.Suit) } func NewDeck() *Deck { self := new(Deck) ranks := []string{"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"} suits := []string{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 }