deck.gno
1.72 Kb ยท 73 lines
1package poker
2
3// Deck manages a 52-card deck with deterministic shuffling
4type Deck struct {
5 Cards []Card
6 Index int // Current deal position
7}
8
9// NewDeck creates a standard 52-card deck
10func NewDeck() *Deck {
11 cards := make([]Card, 52)
12 idx := 0
13 for suit := 0; suit < 4; suit++ {
14 for value := 2; value <= 14; value++ {
15 cards[idx] = Card{Suit: suit, Value: value}
16 idx++
17 }
18 }
19 return &Deck{Cards: cards, Index: 0}
20}
21
22// Shuffle shuffles the deck using a seed-based Fisher-Yates algorithm
23// This is deterministic given the same seed, which is important for
24// blockchain reproducibility. In production, the seed should come from
25// a commit-reveal scheme where all players contribute randomness.
26func (d *Deck) Shuffle(seed int64) {
27 n := len(d.Cards)
28 // Simple LCG (Linear Congruential Generator) for deterministic randomness
29 state := seed
30 for i := n - 1; i > 0; i-- {
31 // LCG: state = (a * state + c) mod m
32 state = (state*6364136223846793005 + 1442695040888963407) % (1 << 62)
33 j := int(abs64(state) % int64(i+1))
34 d.Cards[i], d.Cards[j] = d.Cards[j], d.Cards[i]
35 }
36 d.Index = 0
37}
38
39// Deal deals n cards from the deck
40func (d *Deck) Deal(n int) []Card {
41 if d.Index+n > len(d.Cards) {
42 panic("not enough cards in deck")
43 }
44 cards := make([]Card, n)
45 for i := 0; i < n; i++ {
46 cards[i] = d.Cards[d.Index]
47 d.Index++
48 }
49 return cards
50}
51
52// DealOne deals a single card from the deck
53func (d *Deck) DealOne() Card {
54 cards := d.Deal(1)
55 return cards[0]
56}
57
58// Remaining returns the number of cards remaining in the deck
59func (d *Deck) Remaining() int {
60 return len(d.Cards) - d.Index
61}
62
63// Reset resets the deck to the beginning
64func (d *Deck) Reset() {
65 d.Index = 0
66}
67
68func abs64(x int64) int64 {
69 if x < 0 {
70 return -x
71 }
72 return x
73}