133 lines
2.7 KiB
Go
133 lines
2.7 KiB
Go
package draft
|
|
|
|
import "errors"
|
|
|
|
// Errors that can happen during draft
|
|
var (
|
|
ErrNotInPack = errors.New("card picked not in pack")
|
|
ErrNoPacksLeft = errors.New("no packs left to open")
|
|
)
|
|
|
|
// PodDirection is the direction packs are passed between players
|
|
type PodDirection string
|
|
|
|
// All rotations
|
|
var (
|
|
PRClockwise PodDirection = "left"
|
|
PRAnticlockwise PodDirection = "right"
|
|
)
|
|
|
|
// Pod is a group of players drafting packs/cubes
|
|
type Pod struct {
|
|
Players []*Player
|
|
Direction PodDirection
|
|
}
|
|
|
|
// Player is a single player partecipating in a pod
|
|
type Player struct {
|
|
// Packs and picks
|
|
CurrentPack Pack
|
|
Packs []Pack
|
|
Picks []Card
|
|
|
|
// Nearby players
|
|
left *Player
|
|
right *Player
|
|
|
|
// Pod the player is in
|
|
pod *Pod
|
|
|
|
// Channels for passing stuff around
|
|
newpack chan Pack
|
|
}
|
|
|
|
// MakePod creates a pod with a specified number of players and a given set of packs
|
|
func MakePod(playerCount int, provider PackProvider) *Pod {
|
|
// Make player list
|
|
players := make([]*Player, playerCount)
|
|
|
|
// Make pod
|
|
pod := &Pod{
|
|
Players: players,
|
|
Direction: PRAnticlockwise,
|
|
}
|
|
|
|
// Fill players
|
|
for i := range players {
|
|
players[i] = &Player{
|
|
Packs: provider(),
|
|
Picks: []Card{},
|
|
pod: pod,
|
|
newpack: make(chan Pack, playerCount-1),
|
|
}
|
|
}
|
|
// Second loop to fill nearby players
|
|
for i := range players {
|
|
if i > 0 {
|
|
players[i].left = players[i-1]
|
|
} else {
|
|
players[i].left = players[playerCount-1]
|
|
}
|
|
players[i].right = players[(i+1)%playerCount]
|
|
}
|
|
|
|
return pod
|
|
}
|
|
|
|
// OpenPacks opens the next pack of each player
|
|
func (p *Pod) OpenPacks() error {
|
|
for _, p := range p.Players {
|
|
err := p.OpenPack()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
p.flipDirection()
|
|
return nil
|
|
}
|
|
|
|
func (p *Pod) flipDirection() {
|
|
if p.Direction == PRClockwise {
|
|
p.Direction = PRAnticlockwise
|
|
} else {
|
|
p.Direction = PRClockwise
|
|
}
|
|
}
|
|
|
|
// OpenPack opens the next pack the player has
|
|
func (p *Player) OpenPack() error {
|
|
if len(p.Packs) < 1 {
|
|
return ErrNoPacksLeft
|
|
}
|
|
p.CurrentPack, p.Packs = p.Packs[0], p.Packs[1:]
|
|
return nil
|
|
}
|
|
|
|
// Pick specified what card a player has picked and gives the pack to the next player
|
|
func (p *Player) Pick(pick Card) error {
|
|
// Check that pack contains specified card
|
|
id := -1
|
|
for i, card := range p.CurrentPack {
|
|
if pick.ID == card.ID {
|
|
id = i
|
|
break
|
|
}
|
|
}
|
|
if id < 0 {
|
|
return ErrNotInPack
|
|
}
|
|
// Take card from pack and put it into the picks
|
|
p.Picks = append(p.Picks, p.CurrentPack[id])
|
|
// Remove pick from pack using slice tricks
|
|
p.CurrentPack[id] = p.CurrentPack[len(p.CurrentPack)-1]
|
|
p.CurrentPack = p.CurrentPack[:len(p.CurrentPack)-1]
|
|
|
|
// Send pack to next player
|
|
if p.pod.Direction == PRClockwise {
|
|
p.left.newpack <- p.CurrentPack
|
|
} else {
|
|
p.right.newpack <- p.CurrentPack
|
|
}
|
|
|
|
return nil
|
|
}
|