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 NextRound chan bool } // 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 } } func (p *Pod) checkRound() { for _, player := range p.Players { if len(player.newpack) < 1 { // Someone still hasn't passed a pack return } } // Everyone has new packs to draft p.NextRound <- true } // 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 } p.pod.checkRound() return nil }