public void SelectCards() { if (this.State != GameState.CardSelection) { throw new GameCreationException("This method can only be called during CardSelection!"); } if (_Table != null) { _Table.TearDown(); } this.CardsAvailable = Cards.CardCollection.GetAllCards(c => IsCardAllowed(c)); Cards.CardCollection _CardsChosen = new Cards.CardCollection(); if (this.Settings.Preset != null) { _CardsChosen = this.Settings.Preset.Cards; } else if (this.Settings.Constraints != null) { _CardsChosen.AddRange(this.Settings.Constraints.SelectCards(this.CardsAvailable, 10)); } this.CardsAvailable.RemoveAll(card => _CardsChosen.Contains(card)); _Table = new Table(this, this.Players.Count); _CardsChosen.ForEach(c => _Table.AddKingdomSupply(_Players, c.CardType)); // should now have a list of cards that can be drawn from for things like Bane supplies _Table.SetupSupplies(this); }
public IList <DominionBase.Cards.Card> SelectCards(IList <Cards.Card> availableCards, int numberCardsToSelect) { List <Cards.Card> _CardsChosen = new List <Cards.Card>(); // Remove all "CardDontUse" constraint cards first IList <Cards.Card> usableCards = new List <Cards.Card>(availableCards); foreach (Cards.Constraint constraint in this.Where(c => c.ConstraintType == Cards.ConstraintType.CardDontUse)) { foreach (Cards.Card card in constraint.GetMatchingCards(availableCards)) { usableCards.Remove(card); } } IEnumerable <Constraint> usableConstraints = this.Where(c => c.ConstraintType != Cards.ConstraintType.CardDontUse); Dictionary <Cards.Constraint, IList <Cards.Card> > constraintCards = new Dictionary <Cards.Constraint, IList <Cards.Card> >(); foreach (Cards.Constraint constraint in usableConstraints) { constraintCards[constraint] = new Cards.CardCollection(constraint.GetMatchingCards(availableCards)); } int attempts = 0; // Satisfy Minimum constraints first do { attempts++; _CardsChosen.Clear(); // Add in required cards first foreach (Cards.Constraint constraint in usableConstraints.Where(c => c.ConstraintType == Cards.ConstraintType.CardMustUse)) { _CardsChosen.AddRange(constraintCards[constraint]); } if (_CardsChosen.Count > numberCardsToSelect) { throw new ConstraintException(String.Format("Too many required cards specified in constraints! Please double-check your setup and loosen the requirements. {0} needed & found {1} required constraints.", numberCardsToSelect, _CardsChosen.Count)); } foreach (Cards.Constraint constraint in usableConstraints.OrderByDescending(c => c.Minimum)) { if (constraint.MinimumMet(_CardsChosen)) { continue; } CardCollection discardCards = new CardCollection(); Utilities.Shuffler.Shuffle(constraintCards[constraint]); foreach (Cards.Card card in constraintCards[constraint]) { if (discardCards.Contains(card)) { continue; } if (this.IsChoosable(_CardsChosen, card)) { _CardsChosen.Add(card); if (constraint.MinimumMet(_CardsChosen)) { break; } // Certain constraints (like NumberOfSets) immediately disallow other cards when a card is chosen. // We need to get the list of disallowed cards after each card is added to the list. // This is only needed to ensure the Minimum constraint without taking 10k iterations discardCards.AddRange(constraint.GetCardsToDiscard(_CardsChosen, constraintCards[constraint])); } } } // Give it 50 attempts at trying to satisfy the Minimum requirements if (attempts > 50) { throw new ConstraintException("Cannot satisfy specified constraints! Please double-check and make sure it's possible to construct a Kingdom card setup with the constraints specified."); } } while (!this.MinimumMet(_CardsChosen) || _CardsChosen.Count > numberCardsToSelect); // After satisfying the Minimums, Maximums should be pretty easy to handle List <Cards.Card> _CardsChosenNeeded = new List <Cards.Card>(_CardsChosen); attempts = 0; while (_CardsChosen.Count < numberCardsToSelect) { attempts++; // Give it 50 attempts at trying to satisfy the Minimum requirements if (attempts > 50) { throw new ConstraintException("Cannot satisfy specified constraints! Please double-check and make sure it's possible to construct a Kingdom card setup with the constraints specified."); } _CardsChosen.Clear(); _CardsChosen.AddRange(_CardsChosenNeeded); Utilities.Shuffler.Shuffle(usableCards); foreach (Cards.Card chosenCard in usableCards) { if (_CardsChosen.Contains(chosenCard)) { continue; } if (this.IsChoosable(_CardsChosen, chosenCard)) { _CardsChosen.Add(chosenCard); } if (_CardsChosen.Count == numberCardsToSelect) { break; } } } return(_CardsChosen); }