package poker import "encoding/binary" import crand "crypto/rand" import log "github.com/sirupsen/logrus" import rand "math/rand" type Deck struct { Cards Cards DealIndex int ShuffleSeedVal int64 } 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 NewShuffledDeck() *Deck { d := newDeck() d.ShuffleSeedVal = int64(cryptoUint64()) d.Shuffle() return d } func NewDeckFromSeed(seed int64) *Deck { d := newDeck() d.ShuffleSeedVal = seed d.Shuffle() return d } 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) Shuffle() { //FIXME(sneak) not sure if this is constant time or not rnd := rand.New(rand.NewSource(self.ShuffleSeedVal)) 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) 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) }