protected override ChoiceResult Decide_Stonemason(Choice choice) { switch (choice.ChoiceType) { case ChoiceType.Options: for (int index = choice.Options.Count - 1; index >= 0; index--) { // Overpay by as much as we can properly gain Action cards Currency overpayAmount = new DominionBase.Currency(choice.Options[index].Text); if (this._Game.Table.Supplies.Values.Any(s => s.CanGain() && (s.Category & Category.Action) == Category.Action && s.CurrentCost == overpayAmount)) return new ChoiceResult(new List<String>() { choice.Options[index].Text }); } return base.Decide_Stonemason(choice); case ChoiceType.Cards: return new ChoiceResult(new CardCollection(FindBestCardsToTrash(choice.Cards, 1))); case ChoiceType.Supplies: if (choice.Text.StartsWith("Gain a card costing less than")) return new ChoiceResult(FindBestCardForCost(choice.Supplies.Values, null, false)); else return new ChoiceResult(FindBestCardForCost(choice.Supplies.Values, null, false)); default: return base.Decide_Stonemason(choice); } }
protected override ChoiceResult Decide_Doctor(Choice choice) { switch (choice.ChoiceType) { case ChoiceType.Options: if (choice.Text.StartsWith("Do you want to discard")) { // Choose to trash Copper roughly 1/3 of the time (a little odd, but it should work decently) // Let's change this to be a bit more aggressive // If it's a Curse, Ruins, Hovel, Overgrown Estate, or Rats, trash it // If it's a Copper, or if it's a Silver/Talisman/Quarry and we have at least 1 Platinum and at least 3 Ventures, or if it's a Loan and we have fewer than 3 Coppers if (choice.CardTriggers[0].CardType == Cards.Universal.TypeClass.Curse || (choice.CardTriggers[0].Category & Category.Ruins) == Category.Ruins || choice.CardTriggers[0].CardType == Cards.DarkAges.TypeClass.Hovel || choice.CardTriggers[0].CardType == Cards.DarkAges.TypeClass.OvergrownEstate || choice.CardTriggers[0].CardType == Cards.DarkAges.TypeClass.Rats || choice.CardTriggers[0].CardType == Cards.Universal.TypeClass.Copper || ((choice.CardTriggers[0].CardType == Cards.Universal.TypeClass.Silver || choice.CardTriggers[0].CardType == Cards.Prosperity.TypeClass.Talisman || choice.CardTriggers[0].CardType == Cards.Prosperity.TypeClass.Quarry) && this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.Prosperity.TypeClass.Platinum, true, false) > 0 && this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.Prosperity.TypeClass.Venture, true, false) > 3) || (choice.CardTriggers[0].CardType == Cards.Prosperity.TypeClass.Loan && this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.Universal.TypeClass.Copper, true, false) < 3)) return new ChoiceResult(new List<String>() { choice.Options[1].Text }); // Trash else if ( ((choice.CardTriggers[0].Category & Category.Victory) == Category.Victory && (choice.CardTriggers[0].Category & Category.Action) != Category.Action && (choice.CardTriggers[0].Category & Category.Treasure) != Category.Treasure) || choice.CardTriggers[0].CardType == Cards.Universal.TypeClass.Copper ) return new ChoiceResult(new List<String>() { choice.Options[0].Text }); // Discard else return new ChoiceResult(new List<String>() { choice.Options[2].Text }); // Put it back } else { for (int index = choice.Options.Count - 1; index >= 0; index--) { // Overpay by up to 4 Currency overpayAmount = new DominionBase.Currency(choice.Options[index].Text); if (overpayAmount.Potion.Value > 0 || overpayAmount.Coin.Value > 4) continue; return new ChoiceResult(new List<String>() { choice.Options[index].Text }); } return base.Decide_Doctor(choice); } case ChoiceType.Cards: CardCollection doctorCards = new CardCollection(choice.Cards); // Order them in roughly random order Utilities.Shuffler.Shuffle(doctorCards); return new ChoiceResult(doctorCards); case ChoiceType.SuppliesAndCards: // This should choose cards we don't want. Obvious first targets are Curses, Ruins, Coppers, and perhaps Estates (early, early on) if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.Universal.TypeClass.Curse, false, true) > 0) return new ChoiceResult(choice.Supplies.FirstOrDefault(kvp => kvp.Value.CardType == Cards.Universal.TypeClass.Curse).Value); // Let's get rid of Rats as quickly as possible -- We, as the AI, *HATE* Rats if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.Rats, false, true) > 0) return new ChoiceResult(choice.Supplies.FirstOrDefault(kvp => kvp.Value.CardType == Cards.DarkAges.TypeClass.Rats).Value); // These priorities are based on nothing more than my intuition of how "good" each of the following Ruins cards are if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.RuinedVillage, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.RuinedVillage) }); if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.RuinedMarket, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.RuinedMarket) }); if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.Survivors, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.Survivors) }); if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.Hovel, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.Hovel) }); if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.AbandonedMine, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.AbandonedMine) }); if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.RuinedLibrary, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.RuinedLibrary) }); if (this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.DarkAges.TypeClass.OvergrownEstate, false, true) > 0) return new ChoiceResult(new CardCollection() { choice.Cards.FirstOrDefault(c => c.CardType == Cards.DarkAges.TypeClass.OvergrownEstate) }); if (this.GameProgress > 0.65 && this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.Universal.TypeClass.Estate, false, true) > 0) return new ChoiceResult(choice.Supplies.FirstOrDefault(kvp => kvp.Value.CardType == Cards.Universal.TypeClass.Estate).Value); if (this.GameProgress < 0.65 && this.RealThis.CountAll(this.RealThis, c => c.CardType == Cards.Universal.TypeClass.Copper, false, true) > 0) return new ChoiceResult(choice.Supplies.FirstOrDefault(kvp => kvp.Value.CardType == Cards.Universal.TypeClass.Copper).Value); // We don't want to trash anything useful, so just choose Curse return new ChoiceResult(choice.Supplies.FirstOrDefault(kvp => kvp.Value.CardType == Cards.Universal.TypeClass.Curse).Value); default: return base.Decide_Doctor(choice); } }
protected override ChoiceResult Decide_Herald(Choice choice) { switch (choice.ChoiceType) { case ChoiceType.Options: for (int index = choice.Options.Count - 1; index >= 0; index--) { // Overpay by up to the amount of cards we have in our discard pile, // excluding Coppers, Curses, Ruins, Victory cards, & Shelters Currency overpayAmount = new DominionBase.Currency(choice.Options[index].Text); if (overpayAmount.Potion.Value > 0) continue; if (this.DiscardPile.LookThrough(c => c.CardType != Cards.Universal.TypeClass.Copper && c.CardType != Cards.Universal.TypeClass.Curse && (c.Category & Category.Ruins) != Category.Ruins && (c.Category & Category.Shelter) != Category.Shelter && c.Category != Category.Victory && c.CardType != Cards.Hinterlands.TypeClass.Tunnel).Count >= overpayAmount.Coin.Value) return new ChoiceResult(new List<String>() { choice.Options[index].Text }); } return base.Decide_Herald(choice); case ChoiceType.Cards: // Find highest in-deck value cards to put on top // While ignoring Victory cards, Curses, & Shelters CardCollection heraldCards = new CardCollection(choice.Cards .Where(c => c.Category != Category.Victory && c.CardType != Cards.Universal.TypeClass.Curse && c.CardType != Cards.Hinterlands.TypeClass.Tunnel && (c.Category & Category.Shelter) != Category.Shelter) .OrderByDescending(c => ComputeValueInDeck(c)) .Take(choice.Minimum)); // If this doesn't lead to enough cards, then include Shelters if (heraldCards.Count < choice.Minimum) heraldCards.AddRange(choice.Cards .Where(c => (c.Category & Category.Shelter) == Category.Shelter) .Take(choice.Minimum - heraldCards.Count)); // If this *still* doesn't include enough cards, include Victory cards if (heraldCards.Count < choice.Minimum) heraldCards.AddRange(choice.Cards .Where(c => c.Category == Category.Victory || c.CardType == Cards.Hinterlands.TypeClass.Tunnel) .OrderByDescending(c => ComputeValueInDeck(c)) .Take(choice.Minimum - heraldCards.Count)); // Uh... our deck is absolutely shit. Just take the first however many cards if (heraldCards.Count < choice.Minimum) heraldCards = new CardCollection(choice.Cards .OrderByDescending(c => ComputeValueInDeck(c)) .Take(choice.Minimum)); return new ChoiceResult(heraldCards); default: return base.Decide_Herald(choice); } }
private void UpdateDisplayPlayer(DominionBase.Players.Player player) { bPlayTreasures.IsEnabled = false; bPlayCoinTokens.IsEnabled = false; bBuyPhase.IsEnabled = false; bTurnDone.IsEnabled = false; bUndo.IsEnabled = false; bPlayTreasures.Text = "Play basic _Treasures"; if (player == null) { return; } if (player.PlayerType == DominionBase.Players.PlayerType.Human) { DominionBase.Cards.CardCollection treasures; DominionBase.Currency totalCurrency; String currency = String.Empty; switch (player.Phase) { case DominionBase.Players.PhaseEnum.Action: if (player.PlayerMode == DominionBase.Players.PlayerMode.Normal) { treasures = player.Hand[c => (c.Category & DominionBase.Cards.Category.Treasure) == DominionBase.Cards.Category.Treasure && (c.Location == DominionBase.Cards.Location.General || c.CardType.GetMethod("Play", new Type[] { typeof(DominionBase.Players.Player) }).DeclaringType == typeof(DominionBase.Cards.Card))]; bPlayTreasures.IsEnabled = treasures.Count > 0; totalCurrency = new DominionBase.Currency(); foreach (DominionBase.Currency c in treasures.Select(t => t.Benefit.Currency)) totalCurrency += c; currency = totalCurrency.ToStringInline(); bPlayCoinTokens.IsEnabled = player.TokenPiles.ContainsKey(DominionBase.Cards.Guilds.TypeClass.CoinToken) && player.TokenPiles[DominionBase.Cards.Guilds.TypeClass.CoinToken].Count > 0 && player.CurrentTurn.CardsBought.Count == 0; bBuyPhase.IsEnabled = true; bTurnDone.IsEnabled = true; } break; case DominionBase.Players.PhaseEnum.ActionTreasure: case DominionBase.Players.PhaseEnum.BuyTreasure: if (player.PlayerMode == DominionBase.Players.PlayerMode.Normal) { treasures = player.Hand[c => (c.Category & DominionBase.Cards.Category.Treasure) == DominionBase.Cards.Category.Treasure && (c.Location == DominionBase.Cards.Location.General || c.CardType.GetMethod("Play", new Type[] { typeof(DominionBase.Players.Player) }).DeclaringType == typeof(DominionBase.Cards.Card))]; bPlayTreasures.IsEnabled = treasures.Count > 0; totalCurrency = new DominionBase.Currency(); foreach (DominionBase.Currency c in treasures.Select(t => t.Benefit.Currency)) totalCurrency += c; currency = totalCurrency.ToStringInline(); bPlayCoinTokens.IsEnabled = player.TokenPiles.ContainsKey(DominionBase.Cards.Guilds.TypeClass.CoinToken) && player.TokenPiles[DominionBase.Cards.Guilds.TypeClass.CoinToken].Count > 0 && player.CurrentTurn.CardsBought.Count == 0; bBuyPhase.IsEnabled = true; bTurnDone.IsEnabled = true; } break; case DominionBase.Players.PhaseEnum.Buy: if (player.PlayerMode == DominionBase.Players.PlayerMode.Normal) { bTurnDone.IsEnabled = true; } break; case DominionBase.Players.PhaseEnum.Cleanup: case DominionBase.Players.PhaseEnum.Endgame: break; } bUndo.IsEnabled = player.CurrentTurn.CardsPlayed.Count > 0 && player.CurrentTurn.CardsPlayed[player.CurrentTurn.CardsPlayed.Count - 1].CanUndo && player.CurrentTurn.CardsBought.Count == 0; if (bPlayTreasures.IsEnabled) bPlayTreasures.Text = String.Format("Play basic _Treasures for: {0}", currency); } }