Add support for up to 6 players.

This commit is contained in:
Greyson Parrelli
2026-07-28 07:36:09 -04:00
parent e542118175
commit a4f5f6910d
38 changed files with 2306 additions and 713 deletions
+94 -73
View File
@@ -1291,98 +1291,119 @@ func packTiers(pack string) (*[MaxRounds][]petTemplate, *[MaxRounds][]foodTempla
}
}
// buildShopDecks creates all six tier decks (unshuffled) for the game's pack.
// buildShopDecks creates all six tier decks (unshuffled) from the game's
// selected packs. Combining packs is the rulebook's answer to seating more
// than two players: every pack's tier 1 cards shuffle together into one tier 1
// deck, its tier 2 cards into one tier 2 deck, and so on. A game on a single
// pack is just the one-element case.
func (g *Game) buildShopDecks() {
pets, foods := packTiers(g.Pack)
g.ShopDecks = make([][]Card, MaxRounds)
for tierIdx := range pets {
var deck []Card
for _, t := range pets[tierIdx] {
for _, suit := range t.Suits {
deck = append(deck, Card{
ID: g.newCardID(),
Kind: KindPet,
Name: t.Name,
Tier: tierIdx + 1,
Power: t.Power,
Suit: suit,
Effects: t.Effects,
EffectText: t.EffectText,
})
for _, pack := range g.packList() {
pets, foods := packTiers(pack)
for tierIdx := range pets {
deck := g.ShopDecks[tierIdx]
for _, t := range pets[tierIdx] {
for _, suit := range t.Suits {
deck = append(deck, Card{
ID: g.newCardID(),
Kind: KindPet,
Name: t.Name,
Tier: tierIdx + 1,
Power: t.Power,
Suit: suit,
Effects: t.Effects,
EffectText: t.EffectText,
})
}
}
}
for _, f := range foods[tierIdx] {
for range f.Copies {
deck = append(deck, Card{
ID: g.newCardID(),
Kind: KindFood,
Name: f.Name,
Tier: tierIdx + 1,
Food: f.Food,
Perk: f.Perk,
Effects: f.Effects,
EffectText: f.EffectText,
})
for _, f := range foods[tierIdx] {
for range f.Copies {
deck = append(deck, Card{
ID: g.newCardID(),
Kind: KindFood,
Name: f.Name,
Tier: tierIdx + 1,
Food: f.Food,
Perk: f.Perk,
Effects: f.Effects,
EffectText: f.EffectText,
})
}
}
g.ShopDecks[tierIdx] = deck
}
g.ShopDecks[tierIdx] = deck
}
}
// Catalog returns the default pack's representative cards.
func Catalog() []Card { return CatalogForPack(DefaultPack) }
// packList is the game's pack selection, defaulting to the base pack so a
// zero-value Game (scratch simulations, tests) still builds real decks.
func (g *Game) packList() []string {
if len(g.Packs) == 0 {
return []string{DefaultPack}
}
return g.Packs
}
// CatalogForPack returns one representative card for every pet and food in a
// pack, tier by tier, for the debug "buy any card" panel. IDs are name-based
// placeholders (not real instances); pets use their first printed suit.
func CatalogForPack(pack string) []Card {
pets, foods := packTiers(pack)
// Catalog returns the default pack's representative cards.
func Catalog() []Card { return CatalogForPacks([]string{DefaultPack}) }
// CatalogForPacks returns one representative card for every pet and food in
// the given packs, tier by tier, for the debug "buy any card" panel. IDs are
// name-based placeholders (not real instances); pets use their first printed
// suit. Cards are grouped by tier across all packs, matching how the shop
// decks combine.
func CatalogForPacks(packs []string) []Card {
var cards []Card
for tierIdx := range pets {
for _, t := range pets[tierIdx] {
suit := SuitRed
if len(t.Suits) > 0 {
suit = t.Suits[0]
for tierIdx := range MaxRounds {
for _, pack := range packs {
pets, foods := packTiers(pack)
for _, t := range pets[tierIdx] {
suit := SuitRed
if len(t.Suits) > 0 {
suit = t.Suits[0]
}
cards = append(cards, Card{
ID: "pet-" + t.Name, Kind: KindPet, Name: t.Name, Tier: tierIdx + 1,
Power: t.Power, Suit: suit, Effects: t.Effects, EffectText: t.EffectText,
})
}
for _, f := range foods[tierIdx] {
cards = append(cards, Card{
ID: "food-" + f.Name, Kind: KindFood, Name: f.Name, Tier: tierIdx + 1,
Food: f.Food, Perk: f.Perk, Effects: f.Effects, EffectText: f.EffectText,
})
}
cards = append(cards, Card{
ID: "pet-" + t.Name, Kind: KindPet, Name: t.Name, Tier: tierIdx + 1,
Power: t.Power, Suit: suit, Effects: t.Effects, EffectText: t.EffectText,
})
}
for _, f := range foods[tierIdx] {
cards = append(cards, Card{
ID: "food-" + f.Name, Kind: KindFood, Name: f.Name, Tier: tierIdx + 1,
Food: f.Food, Perk: f.Perk, Effects: f.Effects, EffectText: f.EffectText,
})
}
}
return cards
}
// cardByName mints a fresh instance of the named pet or food from the current
// pack's templates (pets take their first printed suit). Returns false if
// unknown.
// cardByName mints a fresh instance of the named pet or food from the
// templates of any pack in play (pets take their first printed suit). Returns
// false if unknown.
func (g *Game) cardByName(name string) (Card, bool) {
pets, foods := packTiers(g.Pack)
for tierIdx := range pets {
for _, t := range pets[tierIdx] {
if t.Name == name {
suit := SuitRed
if len(t.Suits) > 0 {
suit = t.Suits[0]
for _, pack := range g.packList() {
pets, foods := packTiers(pack)
for tierIdx := range pets {
for _, t := range pets[tierIdx] {
if t.Name == name {
suit := SuitRed
if len(t.Suits) > 0 {
suit = t.Suits[0]
}
return Card{
ID: g.newCardID(), Kind: KindPet, Name: t.Name, Tier: tierIdx + 1,
Power: t.Power, Suit: suit, Effects: t.Effects, EffectText: t.EffectText,
}, true
}
return Card{
ID: g.newCardID(), Kind: KindPet, Name: t.Name, Tier: tierIdx + 1,
Power: t.Power, Suit: suit, Effects: t.Effects, EffectText: t.EffectText,
}, true
}
}
for _, f := range foods[tierIdx] {
if f.Name == name {
return Card{
ID: g.newCardID(), Kind: KindFood, Name: f.Name, Tier: tierIdx + 1,
Food: f.Food, Perk: f.Perk, Effects: f.Effects, EffectText: f.EffectText,
}, true
for _, f := range foods[tierIdx] {
if f.Name == name {
return Card{
ID: g.newCardID(), Kind: KindFood, Name: f.Name, Tier: tierIdx + 1,
Food: f.Food, Perk: f.Perk, Effects: f.Effects, EffectText: f.EffectText,
}, true
}
}
}
}