-
Notifications
You must be signed in to change notification settings - Fork 0
/
deck.go
125 lines (114 loc) · 2.71 KB
/
deck.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package desert
import (
"math/rand"
)
type Deck struct {
cards []Card
watchers []func(DeckEvent)
}
// A DeckEvent is a notification of a change happening to a Deck
// Action will be one of "shuffle", "add", or "draw"
type DeckEvent struct {
Action string `json:"action"`
Card *Card `json:"card"`
Length int `json:"length"`
}
func (d *Deck) Shuffle() {
rand.Shuffle(len(d.cards), func(i, j int) {
d.cards[i], d.cards[j] = d.cards[j], d.cards[i]
})
d.notifyWatchers("shuffle", nil)
}
// Remove a card from the top of the deck, and return that card
func (d *Deck) Draw() (Card, bool) {
if len(d.cards) < 1 {
return Card{}, false
}
c := d.cards[0]
d.cards = d.cards[1:]
d.notifyWatchers("draw", &c)
return c, true
}
// Add a card to the deck
func (d *Deck) Add(c Card) {
d.cards = append(d.cards, c)
d.notifyWatchers("add", &c)
}
// Add a callback function, to be triggered when the deck changes
// The passed function should accept a DeckEvent
func (d *Deck) Watch(fn func(DeckEvent)) {
if d.watchers == nil {
d.watchers = make([]func(DeckEvent), 0, 1)
}
d.watchers = append(d.watchers, fn)
}
func (d *Deck) notifyWatchers(action string, c *Card) {
for _, fn := range d.watchers {
fn(DeckEvent{
Action: action,
Card: c,
Length: len(d.cards),
})
}
}
// Create a default Storm deck
func NewStormDeck() *Deck {
d := &Deck{
cards: make([]Card, 0, 31),
}
directions := []string{"North", "South", "East", "West"}
for dir := range directions {
for i := 0; i < 3; i++ {
d.cards = append(d.cards, Card{
CardType: "STORM_MOVES",
Storm: &stormCard{
Direction: directions[dir],
Distance: 1,
},
})
}
for i := 0; i < 2; i++ {
d.cards = append(d.cards, Card{
CardType: "STORM_MOVES",
Storm: &stormCard{
Direction: directions[dir],
Distance: 2,
},
})
}
d.cards = append(d.cards, Card{
CardType: "STORM_MOVES",
Storm: &stormCard{
Direction: directions[dir],
Distance: 3,
},
})
}
for i := 0; i < 3; i++ {
d.cards = append(d.cards, Card{CardType: "STORM_PICKS_UP"})
}
for i := 0; i < 4; i++ {
d.cards = append(d.cards, Card{CardType: "SUN_BEATS_DOWN"})
}
return d
}
// Create a default Gear deck
func NewGearDeck() *Deck {
d := &Deck{
cards: make([]Card, 0, 31),
}
for i := 0; i < 3; i++ {
d.cards = append(d.cards, Card{CardType: "DUNE_BLASTER"})
}
for i := 0; i < 3; i++ {
d.cards = append(d.cards, Card{CardType: "JET_PACK"})
}
for i := 0; i < 2; i++ {
d.cards = append(d.cards, Card{CardType: "SOLAR_SHIELD"})
}
for i := 0; i < 2; i++ {
d.cards = append(d.cards, Card{CardType: "TERRASCOPE"})
}
d.cards = append(d.cards, Card{CardType: "SECRET_WATER_RESERVE"}, Card{CardType: "TIME_THROTTLE"})
return d
}