Add support for up to 6 players.
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Card packs are the selectable sets of pets and food a game is played with.
|
||||
// Turtle, Golden, and Unicorn all ship with full six-tier card data.
|
||||
|
||||
@@ -31,3 +36,73 @@ func packByID(id string) (PackInfo, bool) {
|
||||
}
|
||||
return PackInfo{}, false
|
||||
}
|
||||
|
||||
// PacksNeeded is how many packs a game must combine to seat n players: the
|
||||
// rulebook asks for at least 2 packs at 4 players and 3 at 6, i.e. one per
|
||||
// pair. More packs than the minimum are always allowed — a deeper shop just
|
||||
// means fewer repeated pets.
|
||||
func PacksNeeded(players int) int {
|
||||
if players < MinPlayers {
|
||||
return 1
|
||||
}
|
||||
return players / 2
|
||||
}
|
||||
|
||||
// sortPacks puts a pack selection into catalog order, so the same choice
|
||||
// always reads the same way in views and logs.
|
||||
func sortPacks(ids []string) []string {
|
||||
out := make([]string, 0, len(ids))
|
||||
for _, p := range Packs {
|
||||
for _, id := range ids {
|
||||
if id == p.ID {
|
||||
out = append(out, p.ID)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// validatePacks checks a pack selection: non-empty, known, playable, and free
|
||||
// of duplicates. It returns the selection in catalog order.
|
||||
func validatePacks(ids []string) ([]string, error) {
|
||||
if len(ids) == 0 {
|
||||
return nil, fmt.Errorf("%w: pick at least one pack", ErrInvalidAction)
|
||||
}
|
||||
seen := map[string]bool{}
|
||||
for _, id := range ids {
|
||||
pack, ok := packByID(id)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w: unknown pack %q", ErrInvalidAction, id)
|
||||
}
|
||||
if !pack.Playable {
|
||||
return nil, fmt.Errorf("%w: the %s isn't available yet", ErrInvalidAction, pack.Name)
|
||||
}
|
||||
if seen[id] {
|
||||
return nil, fmt.Errorf("%w: %s is selected twice", ErrInvalidAction, pack.Name)
|
||||
}
|
||||
seen[id] = true
|
||||
}
|
||||
return sortPacks(ids), nil
|
||||
}
|
||||
|
||||
// PackNames renders a pack selection as a readable list ("Turtle Pack and
|
||||
// Golden Pack") for log lines.
|
||||
func PackNames(ids []string) string {
|
||||
names := make([]string, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
if p, ok := packByID(id); ok {
|
||||
names = append(names, p.Name)
|
||||
}
|
||||
}
|
||||
switch len(names) {
|
||||
case 0:
|
||||
return "no packs"
|
||||
case 1:
|
||||
return names[0]
|
||||
case 2:
|
||||
return names[0] + " and " + names[1]
|
||||
default:
|
||||
return strings.Join(names[:len(names)-1], ", ") + ", and " + names[len(names)-1]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user