using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using DominionBase.Currencies;
using DominionBase.Piles;
using DominionBase.Players;
namespace DominionBase.Cards.Cornucopia
{
public static class TypeClass
{
public static Type BagOfGold = typeof(BagOfGold);
public static Type Diadem = typeof(Diadem);
public static Type Fairgrounds = typeof(Fairgrounds);
public static Type FarmingVillage = typeof(FarmingVillage);
public static Type Followers = typeof(Followers);
public static Type FortuneTeller = typeof(FortuneTeller);
public static Type Hamlet = typeof(Hamlet);
public static Type Harvest = typeof(Harvest);
public static Type HornOfPlenty = typeof(HornOfPlenty);
public static Type HorseTraders = typeof(HorseTraders);
public static Type HuntingParty = typeof(HuntingParty);
public static Type Jester = typeof(Jester);
public static Type Menagerie = typeof(Menagerie);
public static Type Princess = typeof(Princess);
public static Type PrizeSupply = typeof(PrizeSupply);
public static Type Remake = typeof(Remake);
public static Type Tournament = typeof(Tournament);
public static Type TrustySteed = typeof(TrustySteed);
public static Type YoungWitch = typeof(YoungWitch);
public static Type BaneToken = typeof(BaneToken);
}
public class BagOfGold : Card
{
public BagOfGold()
: base("Bag of Gold", Category.Action | Category.Prize, Source.Cornucopia, Location.Special, Group.CardOrdering | Group.PlusAction | Group.Gain)
{
this.BaseCost = new Cost(0, true);
this.Benefit.Actions = 1;
this.Text = "Gain a Gold, putting it on top of your deck.(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
player.Gain(player._Game.Table.Gold, DeckLocation.Deck, DeckPosition.Top);
}
}
public class BaneToken : Token
{
public BaneToken()
: base("B", "Bane")
{
}
public override String Title { get { return "This supply pile is a Bane pile and cards from here may be revealed to block gaining a Curse card from the Young Witch"; } }
public override Boolean ActDefined { get { return true; } }
internal override void Act(Card card, TokenActionEventArgs e)
{
base.Act(card, e);
Player player = e.Actee as Player;
// Already been cancelled -- don't need to process this one
if (e.Cancelled || !e.Actee.Hand.Contains(card))
return;
// Bane token/card only protects against other attackers
if (player == e.Actor)
return;
Choice choice = Choice.CreateYesNoChoice(String.Format("Reveal Bane card {0} to block gaining a Curse card?", card.Name), card, e.ActingCard, player, e);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options[0] == "Yes")
{
player.AddCardInto(DeckLocation.Revealed, e.Actee.RetrieveCardFrom(DeckLocation.Hand, card));
e.Cancelled = true;
player.AddCardInto(DeckLocation.Hand, e.Actee.RetrieveCardFrom(DeckLocation.Revealed, card));
}
}
}
public class Diadem : Card
{
public Diadem()
: base("Diadem", Category.Treasure | Category.Prize, Source.Cornucopia, Location.Special, Group.PlusCoin)
{
this.BaseCost = new Cost(0, true);
this.Benefit.Currency.Coin.Value = 2;
this.Text = "When you play this, +1 per unused Action you have (Action, not Action card).(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
CardBenefit benefit = new CardBenefit();
benefit.Currency += new Coin(player.Actions);
player.ReceiveBenefit(this, benefit);
}
}
public class Fairgrounds : Card
{
public Fairgrounds()
: base("Fairgrounds", Category.Victory, Source.Cornucopia, Location.Kingdom, Group.VariableVPs)
{
this.BaseCost = new Cost(6);
this.Text = "Worth 2 for every 5 differently named cards in your deck (rounded down).";
}
public override int GetVictoryPoints(IEnumerable cards)
{
return base.GetVictoryPoints(cards) + 2 * (cards.GroupBy(card => card.CardType).Count() / 5);
}
}
public class FarmingVillage : Card
{
public FarmingVillage()
: base("Farming Village", Category.Action, Source.Cornucopia, Location.Kingdom, Group.PlusAction | Group.PlusMultipleActions | Group.Discard)
{
this.BaseCost = new Cost(4);
this.Benefit.Actions = 2;
this.Text = "Reveal cards from the top of your deck until you reveal an Action or Treasure card. Put that card into your hand and discard the other cards.";
}
public override void Play(Player player)
{
base.Play(player);
player.BeginDrawing();
while (player.CanDraw)
{
player.Draw(DeckLocation.Revealed);
Card lastRevealed = player.Revealed.Last();
if ((lastRevealed.Category & Cards.Category.Action) == Cards.Category.Action ||
(lastRevealed.Category & Cards.Category.Treasure) == Cards.Category.Treasure)
break;
}
player.EndDrawing();
if (player.Revealed.Count > 0)
player.AddCardToHand(player.RetrieveCardFrom(DeckLocation.Revealed, player.Revealed.Last()));
player.DiscardRevealed();
}
}
public class Followers : Card
{
public Followers()
: base("Followers", Category.Action | Category.Attack | Category.Prize, Source.Cornucopia, Location.Special, Group.PlusCurses | Group.PlusCard | Group.Gain | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(0, true);
this.Benefit.Cards = 2;
this.Text = "Gain an Estate. Each other player gains a Curse and discards down to 3 cards in hand.(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
player.Gain(player._Game.Table.Estate);
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext();
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
// Skip if the attack is blocked (Moat, Lighthouse, etc.)
if (this.IsAttackBlocked[attackee])
continue;
attackee.Gain(player._Game.Table.Curse);
Choice choice = new Choice("Choose cards to discard. You must discard down to 3 cards in hand", this, attackee.Hand, attackee, false, attackee.Hand.Count - 3, attackee.Hand.Count - 3);
ChoiceResult result = attackee.MakeChoice(choice);
attackee.Discard(DeckLocation.Hand, result.Cards);
}
}
}
public class FortuneTeller : Card
{
public FortuneTeller()
: base("Fortune Teller", Category.Action | Category.Attack, Source.Cornucopia, Location.Kingdom, Group.PlusCoin | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(3);
this.Benefit.Currency.Coin.Value = 2;
this.Text = "Each other player reveals cards from the top of his deck until he reveals a Victory or Curse card. He puts it on top and discards the other revealed cards.";
}
public override void Play(Player player)
{
base.Play(player);
// Perform attack on every player
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext(); // skip active player
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
// Skip if the attack is blocked (Moat, Lighthouse, etc.)
if (!attackee.AttackedBy(player, this))
continue;
attackee.BeginDrawing();
while (attackee.CanDraw)
{
attackee.Draw(DeckLocation.Revealed);
if ((attackee.Revealed.Last().Category & Cards.Category.Victory) == Cards.Category.Victory ||
(attackee.Revealed.Last().Category & Cards.Category.Curse) == Cards.Category.Curse)
break;
}
attackee.EndDrawing();
if (attackee.Revealed.Count > 0)
{
Card lastCard = attackee.Revealed.Last();
if ((lastCard.Category & Cards.Category.Victory) == Cards.Category.Victory ||
(lastCard.Category & Cards.Category.Curse) == Cards.Category.Curse)
attackee.AddCardToDeck(attackee.RetrieveCardFrom(DeckLocation.Revealed, lastCard), DeckPosition.Top);
}
attackee.DiscardRevealed();
}
}
}
public class Hamlet : Card
{
public Hamlet()
: base("Hamlet", Category.Action, Source.Cornucopia, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.PlusMultipleActions | Group.PlusBuy | Group.Discard)
{
this.BaseCost = new Cost(2);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Text = "You may discard a card; if you do, +1 Action.You may discard a card; if you do, +1 Buy.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choiceAction = new Choice("You may discard a card for +1 Action.", this, player.Hand, player, false, 0, 1);
ChoiceResult resultAction = player.MakeChoice(choiceAction);
if (resultAction.Cards.Count > 0)
{
player.Discard(DeckLocation.Hand, resultAction.Cards);
player.ReceiveBenefit(this, new CardBenefit() { Actions = 1 });
}
Choice choiceBuy = new Choice("You may discard a card for +1 Buy.", this, player.Hand, player, false, 0, 1);
ChoiceResult resultBuy = player.MakeChoice(choiceBuy);
if (resultBuy.Cards.Count > 0)
{
player.Discard(DeckLocation.Hand, resultBuy.Cards);
player.ReceiveBenefit(this, new CardBenefit() { Buys = 1 });
}
}
}
public class Harvest : Card
{
public Harvest()
: base("Harvest", Category.Action, Source.Cornucopia, Location.Kingdom, Group.PlusCoin | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(5);
this.Text = "Reveal the top 4 cards of your deck, then discard them. +1 per differently named card revealed.";
}
public override void Play(Player player)
{
base.Play(player);
CardCollection newCards = player.Draw(4, DeckLocation.Revealed);
player.DiscardRevealed();
CardBenefit benefit = new CardBenefit();
benefit.Currency += new Coin(newCards.GroupBy(card => card.CardType).Count());
player.ReceiveBenefit(this, benefit);
}
}
public class HornOfPlenty : Card
{
public HornOfPlenty()
: base("Horn of Plenty", Category.Treasure, Source.Cornucopia, Location.Kingdom, Group.Gain | Group.Trash)
{
this.BaseCost = new Cost(5);
this.Text = "When you play this, gain a card costing up to 1 per differently named card you have in play, counting this. If it's a Victory card, trash this.";
this.Benefit.Currency.Coin.Value = 0;
}
public override void Play(Player player)
{
base.Play(player);
List cardTypes = new List();
foreach (Card card in player.Tableau)
{
Type t = card.CardType;
if (!cardTypes.Contains(t))
cardTypes.Add(t);
}
foreach (Card card in player.PreviousTableau)
{
Type t = card.CardType;
if (!cardTypes.Contains(t))
cardTypes.Add(t);
}
Currencies.Coin uniqueCardsInPlay = new Currencies.Coin(cardTypes.Count);
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost <= uniqueCardsInPlay);
Choice choice = new Choice("Gain a card.", this, gainableSupplies, player, false);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
{
player.Gain(result.Supply);
if ((result.Supply.Category & Cards.Category.Victory) == Cards.Category.Victory)
{
player.RetrieveCardFrom(DeckLocation.Tableau, this);
player.Trash(this);
}
}
}
}
public class HorseTraders : Card
{
private Player.AttackedEventHandler _AttackHandler = null;
public HorseTraders()
: base("Horse Traders",
Category.Action | Category.Reaction,
Source.Cornucopia,
Location.Kingdom,
Group.ReactToAttack | Group.Defense | Group.PlusCoin | Group.PlusBuy | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(4);
this.Benefit.Buys = 1;
this.Benefit.Currency.Coin.Value = 3;
this.Benefit.Cards = -2;
this.Text = "
When another player plays an Attack card, you may set this aside from your hand. If you do, then at the start of your next turn, +1 Card and return this to your hand.";
}
public override void AddedTo(DeckLocation location, Player player)
{
base.AddedTo(location, player);
if (location == DeckLocation.Hand)
{
_AttackHandler = new Player.AttackedEventHandler(player_Attacked);
player.Attacked += _AttackHandler;
}
}
internal override void player_Attacked(object sender, AttackedEventArgs e)
{
Player player = sender as Player;
// Horse Traders only protects against other attackers
if (player == e.Attacker)
return;
// Make sure it exists already
if (player.Hand.Contains(this) && !e.Revealable.ContainsKey(TypeClass.HorseTraders))
e.Revealable[TypeClass.HorseTraders] = new AttackReaction(this, String.Format("Reveal {0}", this), player_RevealHorseTraders);
}
internal void player_RevealHorseTraders(Player player, ref AttackedEventArgs e)
{
player.AddCardInto(DeckLocation.Revealed, player.RetrieveCardFrom(DeckLocation.Hand, this));
player.AddCardInto(DeckLocation.PreviousTableau, player.RetrieveCardFrom(DeckLocation.Revealed, this));
e.HandledBy.Add(TypeClass.HorseTraders);
// Attack isn't cancelled... it's just mitigated
}
public override void PlayDuration(Player player)
{
base.PlayDuration(player);
player.ReceiveBenefit(this, new CardBenefit() { Cards = 1 });
player.AddCardInto(DeckLocation.Hand, player.RetrieveCardFrom(DeckLocation.PreviousTableau, this));
}
public override void RemovedFrom(DeckLocation location, Player player)
{
base.RemovedFrom(location, player);
if (_AttackHandler != null)
player.Attacked -= _AttackHandler;
_AttackHandler = null;
}
}
public class HuntingParty : Card
{
public HuntingParty()
: base("Hunting Party", Category.Action, Source.Cornucopia, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Text = "Reveal your hand. Reveal cards from your deck until you reveal a card that isn't a duplicate of one in your hand. Put it into your hand and discard the rest.";
}
public override void Play(Player player)
{
base.Play(player);
player.ReturnHand(player.RevealHand());
Boolean foundUniqueCard = false;
player.BeginDrawing();
while (player.CanDraw)
{
player.Draw(DeckLocation.Revealed);
if (player.Hand[player.Revealed.Last().CardType].Count == 0)
{
foundUniqueCard = true;
break;
}
}
player.EndDrawing();
if (foundUniqueCard && player.Revealed.Count > 0)
player.AddCardToHand(player.RetrieveCardFrom(DeckLocation.Revealed, player.Revealed.Last()));
player.DiscardRevealed();
}
}
public class Jester : Card
{
public Jester()
: base("Jester", Category.Action | Category.Attack, Source.Cornucopia, Location.Kingdom, Group.PlusCurses | Group.PlusCoin | Group.Gain | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(5);
this.Benefit.Currency.Coin.Value = 2;
this.Text = "Each other player discards the top card of his deck. If it's a Victory card he gains a Curse. Otherwise either he gains a copy of the discarded card or you do, your choice.";
}
public override void Play(Player player)
{
base.Play(player);
// Perform attack on every player
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext(); // skip active player
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
// Skip if the attack is blocked (Moat, Lighthouse, etc.)
if (this.IsAttackBlocked[attackee])
continue;
if (attackee.CanDraw)
{
Card card = attackee.Draw(DeckLocation.Revealed);
attackee.DiscardRevealed();
if ((card.Category & Cards.Category.Victory) == Cards.Category.Victory)
{
attackee.Gain(player._Game.Table.Curse);
}
else
{
Supply supply = null;
if (player._Game.Table.Supplies.ContainsKey(card))
supply = player._Game.Table[card];
if (supply != null && supply.CanGain())
{
Choice choice = new Choice(String.Format("Who should receive the copy of {0}?", card), this, new CardCollection() { card },
new List() { player.ToString(), attackee.ToString() }, player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options[0] == player.ToString())
player.Gain(supply);
else
attackee.Gain(supply);
}
}
}
}
}
}
public class Menagerie : Card
{
public Menagerie()
: base("Menagerie", Category.Action, Source.Cornucopia, Location.Kingdom, Group.PlusCard | Group.PlusAction)
{
this.BaseCost = new Cost(3);
this.Benefit.Actions = 1;
this.Text = "Reveal your hand.If there are no duplicate cards in it, +3 Cards.Otherwise, +1 Card";
}
public override void Play(Player player)
{
base.Play(player);
player.ReturnHand(player.RevealHand());
List cardTypes = new List();
foreach (Card card in player.Hand)
{
Type t = card.CardType;
if (!cardTypes.Contains(t))
cardTypes.Add(t);
}
CardBenefit benefit = new CardBenefit();
if (player.Hand.Count == cardTypes.Count)
benefit.Cards = 3;
else
benefit.Cards = 1;
player.ReceiveBenefit(this, benefit);
}
}
public class Princess : Card
{
private Game.CostComputeEventHandler _CostComputeEventHandler = null;
public Princess()
: base("Princess", Category.Action | Category.Prize, Source.Cornucopia, Location.Special, Group.PlusBuy | Group.ModifyCost | Group.Terminal)
{
this.BaseCost = new Cost(0, true);
this.Benefit.Buys = 1;
this.Text = "While this is in play, cards cost 2 less, but not less than 0.(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
}
public override void AddedTo(DeckLocation location, Player player)
{
base.AddedTo(location, player);
if (location == DeckLocation.Tableau)
{
_CostComputeEventHandler = new Game.CostComputeEventHandler(player_PrincessInPlayArea);
player._Game.CostCompute += _CostComputeEventHandler;
}
}
void player_PrincessInPlayArea(object sender, CostComputeEventArgs e)
{
e.Cost.Coin -= 2;
}
public override void RemovedFrom(DeckLocation location, Player player)
{
base.RemovedFrom(location, player);
if (_CostComputeEventHandler != null)
player._Game.CostCompute -= _CostComputeEventHandler;
_CostComputeEventHandler = null;
}
}
public class PrizeSupply : Card
{
public PrizeSupply()
: base("Prize Supply", Category.Prize, Source.Cornucopia, Location.Invisible, Group.None)
{
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
supply.AddTo(new BagOfGold());
supply.AddTo(new Diadem());
supply.AddTo(new Followers());
supply.AddTo(new Princess());
supply.AddTo(new TrustySteed());
}
}
public class Remake : Card
{
public Remake()
: base("Remake", Category.Action, Source.Cornucopia, Location.Kingdom, Group.DeckReduction | Group.Gain | Group.Trash | Group.RemoveCurses | Group.Terminal)
{
this.BaseCost = new Cost(4);
this.Text = "Do this twice. Trash a card from your hand, then gain a card costing exactly 1 more than the trashed card.";
}
public override void Play(Player player)
{
base.Play(player);
for (int count = 0; count < 2; count++)
{
Choice choiceTrash = new Choice("Choose a card to trash", this, player.Hand, player);
ChoiceResult resultTrash = player.MakeChoice(choiceTrash);
player.Trash(player.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards));
if (resultTrash.Cards.Count > 0)
{
Cost trashedCardCost = player._Game.Cost(resultTrash.Cards[0]);
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost == (trashedCardCost + new Coin(1)));
Choice choice = new Choice("Gain a card", this, gainableSupplies, player, false);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply);
}
}
}
}
public class Tournament : Card
{
public Tournament()
: base("Tournament", Category.Action, Source.Cornucopia, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.PlusCoin | Group.Gain | Group.Discard)
{
this.BaseCost = new Cost(4);
this.Benefit.Actions = 1;
this.Text = "Each player may reveal a Province from his hand.If you do, discard it and gain a Prize (from the Prize pile) or a Duchy, putting it on top of your deck.If no-one else does, +1 Card +1.";
}
public override void Play(Player player)
{
base.Play(player);
Boolean playerRevealedProvince = false;
Boolean anyoneElseRevealedProvince = false;
// Perform on every player (including you)
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
while (enumerator.MoveNext())
{
Player actor = enumerator.Current;
if (actor.Hand[Universal.TypeClass.Province].Count == 0)
continue;
Choice showChoice = Choice.CreateYesNoChoice("Do you want to reveal a Province from your hand?", this, actor);
ChoiceResult showResult = actor.MakeChoice(showChoice);
if (showResult.Options[0] == "Yes")
{
Card shownProvince = actor.RetrieveCardsFrom(DeckLocation.Hand, Universal.TypeClass.Province, 1)[0];
actor.AddCardInto(DeckLocation.Revealed, shownProvince);
if (actor == player)
{
playerRevealedProvince = true;
}
else
{
actor.AddCardInto(DeckLocation.Hand, actor.RetrieveCardFrom(DeckLocation.Revealed, shownProvince));
anyoneElseRevealedProvince = true;
}
}
}
if (playerRevealedProvince)
{
player.Discard(DeckLocation.Revealed);
Boolean isOptional = (player._Game.Table[Cards.Universal.TypeClass.Duchy].Count + player._Game.Table.SpecialPiles[TypeClass.PrizeSupply].Count) == 0;
Choice prizeChoice = new Choice("Select a Prize or a Duchy", this, player._Game.Table.SpecialPiles[TypeClass.PrizeSupply], player, isOptional ? 0 : 1, 1);
((CardCollection)prizeChoice.Cards).Add(new Universal.Duchy());
ChoiceResult prizeResult = player.MakeChoice(prizeChoice);
if (prizeResult.Cards.Count > 0)
{
if (prizeResult.Cards[0].CardType == Universal.TypeClass.Duchy)
player.Gain(player._Game.Table.Duchy, DeckLocation.Deck, DeckPosition.Top);
else
player.Gain(player._Game.Table.SpecialPiles[TypeClass.PrizeSupply], prizeResult.Cards[0].CardType, DeckLocation.Deck, DeckPosition.Top);
}
}
if (!anyoneElseRevealedProvince)
{
CardBenefit benefit = new CardBenefit() { Cards = 1 };
benefit.Currency += new Coin(1);
player.ReceiveBenefit(this, benefit);
}
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
Supply prizeSupply = new Supply(game, game.Players, TypeClass.PrizeSupply, Visibility.All);
prizeSupply.Setup();
game.Table.SpecialPiles.Add(TypeClass.PrizeSupply, prizeSupply);
}
}
public class TrustySteed : Card
{
public TrustySteed()
: base("Trusty Steed",
Category.Action | Category.Prize,
Source.Cornucopia,
Location.Special,
Group.PlusCard | Group.PlusAction | Group.PlusMultipleActions | Group.PlusCoin | Group.CardOrdering | Group.Gain)
{
this.BaseCost = new Cost(0, true);
this.Text = "Choose two: +2Cards; +2Actions;+2; or gain 4 Silvers and put your deck into your discard pile.(The choices must be different.)(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
Choice choice = new Choice("Choose 2:", this, new CardCollection() { this }, new List() { "+2Cards", "+2Actions", "+2", "Gain 4 Silvers & discard deck" }, player, null, false, 2, 2);
ChoiceResult result = player.MakeChoice(choice);
foreach (String option in result.Options)
{
CardBenefit benefit = new CardBenefit();
if (option == "+2Cards")
benefit.Cards = 2;
if (option == "+2Actions")
benefit.Actions += 2;
if (option == "+2")
benefit.Currency += new Coin(2);
if (option == "Gain 4 Silvers & discard deck")
{
player.Gain(player._Game.Table.Silver, 4);
player._Game.SendMessage(player, this);
CardCollection cc = player.RetrieveCardsFrom(DeckLocation.Deck);
player.AddCardsInto(DeckLocation.Discard, cc);
}
player.ReceiveBenefit(this, benefit);
}
}
}
public class YoungWitch : Card
{
public YoungWitch()
: base("Young Witch", Category.Action | Category.Attack, Source.Cornucopia, Location.Kingdom, Group.PlusCurses | Group.PlusCard | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(4);
this.Benefit.Cards = 2;
this.Text = "Discard 2 cards. Each other player may reveal a Bane card from his hand. If he doesn't, he gains a Curse.
Setup: Add an extra Kingdom card pile costing 2 or 3 to the Supply. Cards from that pile are Bane cards.";
}
public override String SpecialPresetKey { get { return "Bane"; } }
public override void Play(Player player)
{
base.Play(player);
// discard 2 cards
Choice choiceDiscard = new Choice("Choose two cards to discard", this, player.Hand, player, false, 2, 2);
ChoiceResult resultDiscard = player.MakeChoice(choiceDiscard);
player.Discard(DeckLocation.Hand, resultDiscard.Cards);
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext();
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
if (this.IsAttackBlocked[attackee])
continue;
if (!attackee.TokenActOn(player, this))
continue;
attackee.Gain(player._Game.Table.Curse);
}
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
Card baneCard = null;
try
{
if (game.Settings.Preset != null)
{
baneCard = game.Settings.Preset.CardCards[game.Settings.Preset.Cards.First(c => c.CardType == this.CardType)].ElementAt(0);
}
else
{
IList availableBaneCards = null;
Boolean shouldUseGameConstraints = true;
ConstraintCollection ywConstraints = new ConstraintCollection();
if (game.Settings.CardSettings.ContainsKey(this.Name))
{
CardsSettings ywSettings = game.Settings.CardSettings[this.Name];
shouldUseGameConstraints = (Boolean)ywSettings.CardSettingCollection[typeof(YoungWitch_UseGameConstraints)].Value;
ywConstraints = (ConstraintCollection)ywSettings.CardSettingCollection[typeof(YoungWitch_Constraints)].Value;
}
// need to setup a bane supply pile here; randomly pick an unused supply card type of cost $2 or $3 from
// the Kingdom cards, create a new supply pile of it, and mark it with a Bane token
availableBaneCards = game.CardsAvailable.Where(c => c.BaseCost == new Cost(2) || c.BaseCost == new Cost(3)).ToList();
if (shouldUseGameConstraints)
{
// Skip all "Must Use" constraints
ConstraintCollection constraints = new ConstraintCollection(game.Settings.Constraints.Where(c => c.ConstraintType != ConstraintType.CardMustUse));
availableBaneCards = constraints.SelectCards(availableBaneCards, 1);
}
else
availableBaneCards = ywConstraints.SelectCards(availableBaneCards, 1);
baneCard = availableBaneCards[0];
}
}
catch (DominionBase.Cards.ConstraintException ce)
{
throw new YoungWitchConstraintException(String.Format("Problem setting up Young Witch constraints: {0}", ce.Message));
}
game.CardsAvailable.Remove(baneCard);
game.Table.AddKingdomSupply(game.Players, baneCard.CardType);
game.Table.Supplies[baneCard].Setup();
game.Table.Supplies[baneCard].AddToken(new BaneToken());
}
public override void CheckSetup(Preset preset, Table table)
{
// We need to find out what the Bane card is, remove it from the Preset cards, and add it to our own CardCards in the Preset
foreach (Supply supply in table.Supplies.Values)
{
if (supply.Tokens.Any(t => t.GetType() == TypeClass.BaneToken))
{
// This is our supply!
preset.Cards.Remove(preset.Cards.Find(c => c.CardType == supply.CardType));
this.CheckSetup(preset, Card.CreateInstance(supply.CardType));
}
}
}
public override void CheckSetup(Preset preset, Card card)
{
if (card == null)
return;
preset.CardCards[this] = new CardCollection { card };
}
public override List GetSerializingTypes()
{
return new List() { typeof(YoungWitch_UseGameConstraints), typeof(YoungWitch_Constraints) };
}
public override CardSettingCollection GenerateSettings()
{
CardSettingCollection csc = new CardSettingCollection();
csc.Add(new YoungWitch_UseGameConstraints { Value = false });
csc.Add(new YoungWitch_Constraints { Value = new ConstraintCollection() });
return csc;
}
public override void FinalizeSettings(CardSettingCollection settings)
{
(settings[typeof(YoungWitch_Constraints)].Value as ConstraintCollection).MaxCount = 1;
}
[Serializable]
public class YoungWitch_UseGameConstraints : CardSetting
{
public override String Name { get { return "UseGameConstraints"; } }
public override String Text { get { return "Use Game constraints instead of the ones listed below"; } }
public override String Hint { get { return "Use the defined Game constraints instead of the ones defined here"; } }
public override Type Type { get { return typeof(Boolean); } }
}
[Serializable]
public class YoungWitch_Constraints : CardSetting
{
public override String Name { get { return "Constraints"; } }
public override String Hint { get { return "Constraints to use for selecting a Bane card to use"; } }
public override Type Type { get { return typeof(ConstraintCollection); } }
}
}
public class YoungWitchConstraintException : ConstraintException
{
public YoungWitchConstraintException() { }
public YoungWitchConstraintException(string message) : base(message) { }
public YoungWitchConstraintException(string message, Exception innerException) : base(message, innerException) { }
internal YoungWitchConstraintException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}