package game // SimulateBattle resolves a hypothetical two-player battle between the given // arranged decks (top of deck first) and returns the result. It runs on a // scratch game, so it never touches real state — callers (notably the AI // player) can roll out as many what-if battles as they like. Dice rolls are // random unless rollDie is non-nil. func SimulateBattle(round, prioritySeat int, deckA, deckB []Card, rollDie func() int) *BattleResult { g := &Game{ Round: round, PrioritySeat: prioritySeat, RollDie: rollDie, // Cards minted during the simulation (apples, bees) get IDs far away // from real ones, purely to avoid confusion when reading results. NextCardID: 1_000_000, Players: []*Player{ {Name: "A", Seat: 0, Deck: append([]Card(nil), deckA...)}, {Name: "B", Seat: 1, Deck: append([]Card(nil), deckB...)}, }, // Rollouts never pause for a mid-battle decision; a fixed policy resolves // them (Golden pack: Nurse Shark). autoBattleDecide: true, } g.startBattle() return g.Battle } // TierContents returns the full printed contents of a tier's shop deck for the // default pack. Cards carry placeholder IDs; they are reference data, not live // instances. func TierContents(tier int) []Card { return TierContentsForPack(DefaultPack, tier) } // TierContentsForPack returns a pack's printed tier contents — public // information from the box. Used by the AI, which decides from a View that // names its pack. func TierContentsForPack(pack string, tier int) []Card { scratch := &Game{Pack: pack} scratch.buildShopDecks() if tier < 1 || tier > len(scratch.ShopDecks) { return nil } return scratch.ShopDecks[tier-1] }