|
|
|
@ -9,17 +9,17 @@ 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 |
|
|
|
@ -35,33 +35,25 @@ type Cards []*Card |
|
|
|
|
|
|
|
|
|
type Deck struct { |
|
|
|
|
Cards Cards |
|
|
|
|
Dealt int |
|
|
|
|
DealIndex int |
|
|
|
|
ShuffleSeedVal int64 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func cryptoUint64() (v uint64) { |
|
|
|
|
err := binary.Read(crand.Reader, binary.BigEndian, &v) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatal(err) |
|
|
|
|
func formatCardsForTerminal(c Cards) (output string) { |
|
|
|
|
var cardstrings []string |
|
|
|
|
for i := 0; i < len(c); i++ { |
|
|
|
|
cardstrings = append(cardstrings, formatCardForTerminal(*c[i])) |
|
|
|
|
} |
|
|
|
|
log.Debugf("crand cryptosource is returning Uint64: %d", v) |
|
|
|
|
return v |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func NewRandom() *rand.Rand { |
|
|
|
|
|
|
|
|
|
trueRandom := true |
|
|
|
|
|
|
|
|
|
var rnd *rand.Rand |
|
|
|
|
output = strings.Join(cardstrings, ",") |
|
|
|
|
return output |
|
|
|
|
|
|
|
|
|
return rnd |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Card) String() string { |
|
|
|
|
func formatCardForTerminal(c Card) (output string) { |
|
|
|
|
var rank string |
|
|
|
|
var suit string |
|
|
|
|
color := Red |
|
|
|
|
switch self.Suit { |
|
|
|
|
switch c.Suit { |
|
|
|
|
case DIAMOND: |
|
|
|
|
color = Blue |
|
|
|
|
case HEART: |
|
|
|
@ -72,9 +64,23 @@ func (self *Card) String() string { |
|
|
|
|
color = Black |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rank = fmt.Sprintf("%s", BgGray(Bold(color(self.Rank)))) |
|
|
|
|
suit = fmt.Sprintf("%s", BgGray(Bold(color(self.Suit)))) |
|
|
|
|
return fmt.Sprintf("%s%s", rank, suit) |
|
|
|
|
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 { |
|
|
|
@ -82,7 +88,7 @@ func NewDeck() *Deck { |
|
|
|
|
self := new(Deck) |
|
|
|
|
|
|
|
|
|
ranks := []string{"A", "2", "3", "4", "5", "6", "7", |
|
|
|
|
"8", "9", "10", "J", "Q", "K"} |
|
|
|
|
"8", "9", "T", "J", "Q", "K"} |
|
|
|
|
|
|
|
|
|
suits := []string{HEART, DIAMOND, CLUB, SPADE} |
|
|
|
|
|
|
|
|
@ -98,7 +104,7 @@ func NewDeck() *Deck { |
|
|
|
|
tot++ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
self.Dealt = 0 |
|
|
|
|
self.DealIndex = 0 |
|
|
|
|
return self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -106,28 +112,37 @@ 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) ShuffleDeterministic(int64 seed) { |
|
|
|
|
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.Dealt + n) > len(self.Cards) { |
|
|
|
|
if (self.DealIndex + n) > len(self.Cards) { |
|
|
|
|
return output |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for i := 0; i < n; i++ { |
|
|
|
|
card := self.Cards[self.Dealt+1] |
|
|
|
|
output = append(output, card) |
|
|
|
|
self.Dealt++ |
|
|
|
|
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++ { |
|
|
|
@ -142,12 +157,51 @@ func generate() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func proto() { |
|
|
|
|
|
|
|
|
|
myDeck := NewDeck() |
|
|
|
|
myDeck.Shuffle() |
|
|
|
|
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: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|