package game import ( "fmt" "log" "math/rand" "strings" ) type Draft struct { players []*Player cardsPerPack int packSize int packsPerPlayer int sets []SetIdentifier } func NewDraftFromDesc(players []*Player, desc string) *Draft { var setList string s := strings.Split(desc, ":") desc, setList = s[0], s[1] if sets, err := SetListToSets(setList); err != nil { log.Fatal(err) } else { return NewDraft(players, desc, sets) } // not reachable return nil } func NewDraft(players []*Player, desc string, sets []SetIdentifier) *Draft { d := &Draft{players: players, sets: sets} d.parseDesc(desc) log.Printf("created new draft %v\n", d) return d } func (d *Draft) parseDesc(desc string) { fmt.Sscanf(desc, "%dx[%d;%d]", &d.packsPerPlayer, &d.cardsPerPack, &d.packSize) } func (d *Draft) PackSize() int { return d.packSize } func (d *Draft) Valid() bool { return !(d.packSize < d.cardsPerPack*len(d.players)) } // run the draft // This method only returns after the draft has finished. func (d *Draft) Run() { pool := NewPileOfCards() requiredCards := d.packsPerPlayer * d.packSize for pool.Size() < requiredCards { for _, set := range d.sets { setDeck := NewDeck() for _, c := range NewDeckFromCardPaths(set.CardPaths()).Cards() { if c.IsBuyable() { setDeck.AddCard(c) } } setDeck.MoveInto(pool) } } nPlayers := len(d.players) packs := make([]PileOfCards, 0, nPlayers*d.packsPerPlayer) for range len(d.players) * d.packsPerPlayer { pack := NewRandomPackFromPool(pool, d.packSize) packs = append(packs, pack) } log.Printf("%d %d %d\n", d.packsPerPlayer, d.cardsPerPack, len(d.players)) for i := range d.packsPerPlayer { for j := range d.cardsPerPack * len(d.players) { for k, player := range d.players { pack := packs[i*nPlayers+(k+j)%nPlayers] pickPrompt := newDraftPickPrompt(pack) log.Printf("prompt %s for a pick from pack %d\n", player.Name, i*nPlayers+(k+j)%nPlayers) pick := prompt(player.Ctrl, pickPrompt) pick.resolve(player.gameState) } } } } func (d *Draft) AddPlayer(p *Player) { if p.Ctrl == nil { log.Fatal("added player without control") } d.players = append(d.players, p) } type randomDraftAiCtrl struct { ai *Player pack PileOfCards } func (ctrl *randomDraftAiCtrl) Player() *Player { return ctrl.ai } func (ctrl *randomDraftAiCtrl) Close() { } func (ctrl *randomDraftAiCtrl) SendNotification(n PlayerNotification) { ctrl.pack = n.Context.(PileOfCards) } func (ctrl *randomDraftAiCtrl) RecvAction() Action { availCards := ctrl.pack.Cards() var pick int if n := len(availCards); n > 1 { pick = rand.Intn(n - 1) } else { pick = 0 } return NewDraftPick(ctrl.ai, ctrl.pack, availCards[pick]) } func (d *Draft) AddRandomAi() { p := &Player{Id: -1, Name: "randomDraftAI", Deck: NewDeck()} p.Ctrl = &randomDraftAiCtrl{ai: p} d.players = append(d.players, p) }