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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
package game
import (
"errors"
"fmt"
"math/rand"
"strings"
"golang.org/x/exp/slices"
)
type PileOfCards interface {
Size() int
IsEmpty() bool
Contains(*Card) bool
Cards() []*Card
AddCards(cards []*Card)
AddCard(card *Card)
RemoveCard(card *Card)
MoveCard(card *Card, into PileOfCards)
MoveInto(into PileOfCards)
ToList() string
}
type PileOfCardsBase struct {
cards []*Card
}
func NewPileOfCards() *PileOfCardsBase {
return &PileOfCardsBase{[]*Card{}}
}
// Stringify to a []-bracket enclosed comma-seperated list of card names.
func (poc *PileOfCardsBase) String() string {
cardNames := make([]string, 0, len(poc.Cards()))
for _, card := range poc.Cards() {
cardNames = append(cardNames, card.Path())
}
return fmt.Sprintf("[%s]", strings.Join(cardNames, ", "))
}
var InvalidPocString = errors.New("Invalid PileOfCards format")
// Initialise a PileOfCard from a string.
// Return InvalidPocString on error.
func (poc *PileOfCardsBase) FromString(in string) error {
if in[0] != '[' || in[len(in)-1] != ']' {
return InvalidPocString
}
in = in[1 : len(in)-1]
for cardName := range strings.SplitSeq(in, ", ") {
if card, err := NewCardSafe(cardName); err != nil {
return err
} else {
poc.AddCard(card)
}
}
return nil
}
func (poc *PileOfCardsBase) Size() int {
return len(poc.cards)
}
func (poc *PileOfCardsBase) IsEmpty() bool {
return poc.Size() == 0
}
func (poc *PileOfCardsBase) Contains(card *Card) bool {
return slices.Contains(poc.cards, card)
}
func (poc *PileOfCardsBase) Cards() []*Card {
return poc.cards
}
func (poc *PileOfCardsBase) AddPoc(toAdd PileOfCards) {
poc.AddCards(toAdd.Cards())
}
func (poc *PileOfCardsBase) AddCards(cards []*Card) {
for _, card := range cards {
poc.AddCard(card)
}
}
func (poc *PileOfCardsBase) AddCard(card *Card) {
// Tokens can not be part of any pile of cards
if !card.IsToken() {
poc.cards = append(poc.cards, card)
}
}
func (poc *PileOfCardsBase) RemoveCard(card *Card) {
ncards := poc.Size()
for i, c := range poc.cards {
if c != card {
continue
}
poc.cards[i] = poc.cards[ncards-1]
poc.cards = poc.cards[:ncards-1]
return
}
}
func (poc *PileOfCardsBase) MoveCard(c *Card, into PileOfCards) {
poc.RemoveCard(c)
into.AddCard(c)
}
func (poc *PileOfCardsBase) MoveInto(into PileOfCards) {
into.AddCards(poc.cards)
poc.cards = []*Card{}
}
func (poc *PileOfCardsBase) ToList() (list string) {
m := make(map[string]int)
for _, card := range poc.cards {
path := card.Path()
m[path]++
}
for path, amount := range m {
list += fmt.Sprintf("%d %s\n", amount, path)
}
return list[:len(list)-1]
}
func NewRandomPackFromPool(pool PileOfCards, packSize int) PileOfCards {
pack := NewPileOfCards()
for _ = range packSize {
card := pool.Cards()[rand.Intn(len(pool.Cards())-1)]
pool.MoveCard(card, pack)
}
return pack
}
|