2019-03-24 04:13:06 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-05-19 00:33:15 +00:00
|
|
|
func (d *Deck) FormatForTerminal() string {
|
|
|
|
return d.Cards.FormatForTerminal()
|
|
|
|
}
|
|
|
|
|
2019-03-24 04:13:06 +00:00
|
|
|
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)
|
|
|
|
}
|