draft/mlp/booster.go

138 lines
3.5 KiB
Go

package mlp
import (
"math/rand"
"git.fromouter.space/mcg/draft"
)
/*
(This data was taken from the MLP:CCG wikia at mlpccg.fandom.com and confirmed
by people at the MLP:CCG Discord)
Distribution rates for packs is usually 8 commons, 3 uncommons and 1 rare.
No Fixed or Promo cards can be found in packs.
UR distribution depends on set:
- PR has 1/13 chance of UR replacing a common
- CN->AD has 1/11 chance of UR replacing a common
- EO->FF has 1/3 chance of SR/UR replacing a common
SR are twice as common as UR, so that's one more thing to keep in mind.
Lastly, RR can replace another common in the ratio of ~1/2 every 6 boxes, depending
on set. Specifically, this is the RR ratio for each set:
- EO->HM: 1/108
- MT->FF: 1/216
*/
// BoxSchema returns the pack schema from a booster box for a specific set
func (set *Set) BoxSchema() draft.PackSchema {
// Return blank schemas for invalid sets
if set.ID == SetRockNRave || set.ID == SetCelestialSolstice {
return draft.PackSchema{}
}
var rr []draft.AlternateProvider
var srur []draft.AlternateProvider
// Check for RR chances
switch set.ID {
case SetEquestrialOdysseys,
SetHighMagic:
rr = []draft.AlternateProvider{
{
Probability: 1.0 / 108.0,
Provider: set.ProviderByRarity(RarityRoyalRare),
},
}
case SetMarksInTime,
SetDefendersOfEquestria,
SetSeaquestriaBeyond,
SetFriendsForever:
rr = []draft.AlternateProvider{
{
Probability: 1.0 / 216.0,
Provider: set.ProviderByRarity(RarityRoyalRare),
},
}
}
// Check for SR/UR chances
switch set.ID {
case SetPremiere:
srur = []draft.AlternateProvider{
{
Probability: 1.0 / 13.0,
Provider: set.ProviderByRarity(RarityUltraRare),
},
}
case SetCanterlotNights,
SetCrystalGames,
SetAbsoluteDiscord:
srur = []draft.AlternateProvider{
{
Probability: 1.0 / 11.0,
Provider: set.ProviderByRarity(RarityUltraRare),
},
}
default:
srur = []draft.AlternateProvider{
{
Probability: (1.0 / 9.0) * 2.0,
Provider: set.ProviderByRarity(RaritySuperRare),
}, {
Probability: 1.0 / 9.0,
Provider: set.ProviderByRarity(RarityUltraRare),
},
}
}
return draft.PackSchema{
Slots: []draft.PackSlot{
// Fixed common slots
{Amount: 6, Provider: set.ProviderByRarity(RarityCommon)},
// Common slot that can be replaced by RR
{Amount: 1, Provider: set.ProviderByRarity(RarityCommon), Alternate: rr},
// Common slot that can be replaced by SR/UR
{Amount: 1, Provider: set.ProviderByRarity(RarityCommon), Alternate: srur},
// Fixed rare and uncommon slots
{Amount: 1, Provider: set.ProviderByRarity(RarityRare)},
{Amount: 3, Provider: set.ProviderByRarity(RarityUncommon)},
},
}
}
// ProviderByRarity returns a provider for a given rarity level from a given set
func (set *Set) ProviderByRarity(rarity Rarity) draft.CardProvider {
var collection []draft.Card
// RR flow is super easy, just pick one from our hardcoded list
if rarity == RarityRoyalRare {
rr, ok := royalRares[set.ID]
// If asking for RR from a set that doesn't have one, exit early
if !ok {
return nil
}
collection = rr
} else {
//TODO Filter cards by rarity
for _, card := range set.Cards {
if card.Rarity == rarity {
collection = append(collection, draft.Card{ID: card.ID})
}
}
}
return func(n int) []draft.Card {
out := make([]draft.Card, n)
for n := range out {
// Pick a RR at random
idx := rand.Intn(len(collection))
out[n] = collection[idx]
}
return out
}
}