package pokercore import ( "fmt" rand "math/rand" "sync" ) type Deck struct { mu sync.Mutex Cards Cards ShuffleSeedVal int64 Dealt int } func NewDeckFromCards(cards Cards) *Deck { d := new(Deck) d.Cards = make([]Card, len(cards)) copy(d.Cards, cards) return d } func NewEmptyDeck() *Deck { d := new(Deck) d.Cards = make([]Card, 0) return d } // NewDeck returns a new deck of 52 sorted cards. func NewDeck() *Deck { d := NewEmptyDeck() ranks := []Rank{ ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING} // This is the suit order used by dealers at // The Golden Nugget in Las Vegas. suits := []Suit{SPADE, HEART, DIAMOND, CLUB} for _, s := range suits { for _, r := range ranks { d.AddCard(Card{Rank: r, Suit: s}) } } return d } func (d *Deck) AddCard(c Card) { d.mu.Lock() defer d.mu.Unlock() d.Cards = append(d.Cards, c) } // ShuffleRandomly shuffles the deck using cryptographically random numbers. func (d *Deck) ShuffleRandomly() { d.mu.Lock() defer d.mu.Unlock() rnd := rand.New(rand.NewSource(int64(cryptoUint64()))) //FIXME(sneak) not sure if this is constant time or not rnd.Shuffle(len(d.Cards), func(i, j int) { d.Cards[i], d.Cards[j] = d.Cards[j], d.Cards[i] }) } // ShuffleDeterministically shuffles the deck using a deterministic seed for testing. func (d *Deck) ShuffleDeterministically(seed int64) { d.mu.Lock() defer d.mu.Unlock() r := rand.New(rand.NewSource(seed)) //FIXME(sneak) not sure if this is constant time or not r.Shuffle(len(d.Cards), func(i, j int) { d.Cards[i], d.Cards[j] = d.Cards[j], d.Cards[i] }) } // Deal removes n cards from the top of the deck and returns them. The Deck is // modified in place.to remove the dealt cards, just like in real life. func (d *Deck) Deal(n int) (output Cards) { d.mu.Lock() defer d.mu.Unlock() for i := 0; i < n; i++ { output = append(output, d.Cards[i]) } d.Cards = d.Cards[n:] d.Dealt += n return output } func (d *Deck) FormatForTerminal() string { return d.Cards.FormatForTerminal() } func (d *Deck) String() string { return fmt.Sprintf("Deck{%s size=%d dealt=%d}", d.Cards, d.Count(), d.Dealt) } func (d *Deck) Count() int { return len(d.Cards) }