draft/mlp/i8pcube.go

160 lines
4.2 KiB
Go
Raw Normal View History

2019-05-31 09:35:34 +00:00
package mlp
2019-05-31 12:21:50 +00:00
import (
"math/rand"
"git.fromouter.space/mcg/draft"
)
2019-05-31 09:35:34 +00:00
2019-05-31 09:36:22 +00:00
// I8PCube is a cube that uses I8Pages' pack schema
2019-05-31 09:35:34 +00:00
// I8Pages' cube uses different kinds of packs, so a single schema is not possible.
// Therefore, I8PCube itself is not a valid set, but contains two valid sets for
// both types of packs (main deck / problems)
2019-05-31 12:21:50 +00:00
//
// Infos on I8Pages' cube:
// https://docs.google.com/spreadsheets/d/1Ufz4QLwLCZ1vLemAhE6cuAmu2lq_VAN7RhLO9p1opNQ
2019-05-31 09:35:34 +00:00
type I8PCube struct {
Main *I8PSet
Problems *I8PSet
}
// I8PSet is one of the sets of packs contained in a I8PCube
type I8PSet struct {
2019-05-31 12:21:50 +00:00
Cards I8PPool
2019-05-31 09:35:34 +00:00
Schema draft.PackSchema
}
2019-05-31 12:21:50 +00:00
// I8PType is a category of cards to be seeded into packs
type I8PType string
// All types used for seeding packs
const (
I8PTypeBlue I8PType = "blue"
I8PTypeOrange I8PType = "orange"
I8PTypePink I8PType = "pink"
I8PTypePurple I8PType = "purple"
I8PTypeWhite I8PType = "white"
I8PTypeYellow I8PType = "yellow"
I8PTypeNone I8PType = "none"
I8PTypeMulti I8PType = "multi"
I8PTypeEntry I8PType = "entry"
I8PTypeProblem I8PType = "problem"
)
// I8PPool is a pool of card divided into categories
type I8PPool map[I8PType][]Card
2019-05-31 09:35:34 +00:00
// MakeI8PCube takes an organized set of cards and sorts them into a draftable I8PCube
2019-05-31 12:21:50 +00:00
func MakeI8PCube(cards I8PPool) *I8PCube {
2019-05-31 09:35:34 +00:00
return &I8PCube{
2019-05-31 12:21:50 +00:00
Main: makeMainSet(cards),
Problems: makeProblemSet(cards),
}
}
func makeMainSet(cards I8PPool) (set *I8PSet) {
set = &I8PSet{
Cards: I8PPool{
I8PTypeBlue: cards[I8PTypeBlue],
I8PTypeOrange: cards[I8PTypeOrange],
I8PTypePink: cards[I8PTypePink],
I8PTypePurple: cards[I8PTypePurple],
I8PTypeWhite: cards[I8PTypeWhite],
I8PTypeYellow: cards[I8PTypeYellow],
I8PTypeNone: cards[I8PTypeNone],
I8PTypeMulti: cards[I8PTypeMulti],
I8PTypeEntry: cards[I8PTypeEntry],
},
}
//TODO Make schema more flexible
set.Schema = draft.PackSchema{
Slots: []draft.PackSlot{
{Amount: 1, Provider: set.ProviderByType(I8PTypeBlue)},
{Amount: 1, Provider: set.ProviderByType(I8PTypeOrange)},
{Amount: 1, Provider: set.ProviderByType(I8PTypePink)},
{Amount: 1, Provider: set.ProviderByType(I8PTypePurple)},
{Amount: 1, Provider: set.ProviderByType(I8PTypeWhite)},
{Amount: 1, Provider: set.ProviderByType(I8PTypeYellow)},
{Amount: 1, Provider: set.ProviderByType(I8PTypeNone)},
{Amount: 2, Provider: set.ProviderByType(I8PTypeMulti)},
{Amount: 2, Provider: set.ProviderByType(I8PTypeEntry)},
{Amount: 1, Provider: set.ProviderOther()},
},
}
return
}
func makeProblemSet(cards I8PPool) (set *I8PSet) {
set = &I8PSet{
Cards: I8PPool{
I8PTypeProblem: cards[I8PTypeProblem],
},
}
set.Schema = draft.PackSchema{
Slots: []draft.PackSlot{
{
Amount: 12,
Provider: set.ProviderByType(I8PTypeProblem),
},
2019-05-31 09:35:34 +00:00
},
}
2019-05-31 12:21:50 +00:00
return
}
// ProviderByType provides cards from a specified category
func (s *I8PSet) ProviderByType(typ I8PType) draft.CardProvider {
return func(n int) (out []draft.Card) {
s.shuffle(typ)
if len(s.Cards[typ]) < n {
n = len(s.Cards[typ])
}
out, s.Cards[typ] = toDraft(s.Cards[typ][:n]), s.Cards[typ][n:]
return
}
}
// ProviderOther picks a random card for any available set (except Problems)
func (s *I8PSet) ProviderOther() draft.CardProvider {
choices := []I8PType{
I8PTypeBlue,
I8PTypeOrange,
I8PTypePink,
I8PTypePurple,
I8PTypeWhite,
I8PTypeYellow,
I8PTypeNone,
I8PTypeMulti,
I8PTypeEntry,
}
return func(n int) (out []draft.Card) {
// Filter types that have enough cards for what we need
// n is almost always 1, so this should not introduce bias
available := []I8PType{}
for _, typ := range choices {
if len(s.Cards[typ]) >= n {
available = append(available, typ)
}
}
// Check if there are no pools we can pick stuff from, and exit early
// THIS IS NOT NORMAL, AND YOU SHOULD FIX YOUR CUBE!
if len(available) < 1 {
return
}
typ := available[rand.Intn(len(available))]
return s.ProviderByType(typ)(n)
}
}
// PackSchema returns the pack schema for building packs from a I8PCube
func (s *I8PSet) PackSchema() draft.PackSchema {
return s.Schema
}
func (s *I8PSet) shuffle(typ I8PType) {
rand.Shuffle(len(s.Cards[typ]), func(i, j int) {
s.Cards[typ][i], s.Cards[typ][j] = s.Cards[typ][j], s.Cards[typ][i]
})
2019-05-31 09:35:34 +00:00
}