pokercore/deck.go

99 lines
2.2 KiB
Go

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)
}