using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DominionBase.Currencies;
using DominionBase.Piles;
using DominionBase.Players;
namespace DominionBase.Cards.DarkAges
{
public static class TypeClass
{
public static Type AbandonedMine = typeof(AbandonedMine); // Tested
public static Type Altar = typeof(Altar); // Tested
public static Type Armory = typeof(Armory); // Ready for testing
//public static Type BandOfMisfits = typeof(BandOfMisfits); // Unimplemented
public static Type BanditCamp = typeof(BanditCamp); // Tested
public static Type Beggar = typeof(Beggar); // Ready for testing
public static Type Catacombs = typeof(Catacombs); // Needs Standard AI implemented
public static Type Count = typeof(Count); // Ready for testing
public static Type Counterfeit = typeof(Counterfeit); // Ready for testing
public static Type Cultist = typeof(Cultist); // Tested
public static Type DameAnna = typeof(DameAnna); // Ready for testing
public static Type DameJosephine = typeof(DameJosephine); // Ready for testing
public static Type DameMolly = typeof(DameMolly); // Ready for testing
public static Type DameNatalie = typeof(DameNatalie); // Ready for testing
public static Type DameSylvia = typeof(DameSylvia); // Ready for testing
public static Type DeathCart = typeof(DeathCart); // Needs Standard AI implemented
public static Type Feodum = typeof(Feodum); // Tested
public static Type Forager = typeof(Forager); // Needs Standard AI implemented
public static Type Fortress = typeof(Fortress); // Ready for testing
public static Type Graverobber = typeof(Graverobber); // Tested
public static Type Hermit = typeof(Hermit); // Tested
public static Type Hovel = typeof(Hovel); // Tested
public static Type HuntingGrounds = typeof(HuntingGrounds); // Ready for testing
public static Type Ironmonger = typeof(Ironmonger); // Ready for testing
public static Type JunkDealer = typeof(JunkDealer); // Ready for testing
public static Type Knights = typeof(Knights); // Ready for testing
public static Type Madman = typeof(Madman); // Tested
public static Type Marauder = typeof(Marauder); // Tested
public static Type MarketSquare = typeof(MarketSquare); // Ready for testing
public static Type Mercenary = typeof(Mercenary); // Ready for testing
public static Type Mystic = typeof(Mystic); // Tested
public static Type Necropolis = typeof(Necropolis); // Tested
public static Type OvergrownEstate = typeof(OvergrownEstate); // Tested
public static Type Pillage = typeof(Pillage); // Tested
public static Type PoorHouse = typeof(PoorHouse); // Tested
public static Type Procession = typeof(Procession); // Needs Standard AI implemented
public static Type Rats = typeof(Rats); // Tested
public static Type Rebuild = typeof(Rebuild); // Ready for testing
public static Type Rogue = typeof(Rogue); // Ready for testing
public static Type RuinedLibrary = typeof(RuinedLibrary); // Tested
public static Type RuinedMarket = typeof(RuinedMarket); // Tested
public static Type RuinedVillage = typeof(RuinedVillage); // Tested
public static Type RuinsSupply = typeof(RuinsSupply); // Tested
public static Type Sage = typeof(Sage); // Tested
public static Type Scavenger = typeof(Scavenger); // Ready for testing
public static Type Shelters = typeof(Shelters); // Tested
public static Type SirBailey = typeof(SirBailey); // Ready for testing
public static Type SirDestry = typeof(SirDestry); // Ready for testing
public static Type SirMartin = typeof(SirMartin); // Ready for testing
public static Type SirMichael = typeof(SirMichael); // Ready for testing
public static Type SirVander = typeof(SirVander); // Ready for testing
public static Type Spoils = typeof(Spoils); // Tested
public static Type Squire = typeof(Squire); // Tested
public static Type Storeroom = typeof(Storeroom); // Ready for testing
public static Type Survivors = typeof(Survivors); // Tested
public static Type Urchin = typeof(Urchin); // Needs Standard AI implemented
public static Type Vagrant = typeof(Vagrant); // Ready for testing
public static Type WanderingMinstrel = typeof(WanderingMinstrel); // Ready for testing
}
public class AbandonedMine : Card
{
public AbandonedMine()
: base("Abandoned Mine", Category.Action | Category.Ruins, Source.DarkAges, Location.General, Group.PlusCoin | Group.Terminal)
{
this.BaseCost = new Cost(0);
this.Benefit.Currency.Coin.Value = 1;
}
public override Type BaseType { get { return TypeClass.RuinsSupply; } }
}
public class Altar : Card
{
public Altar()
: base("Altar", Category.Action, Source.DarkAges, Location.Kingdom, Group.Gain | Group.Trash | Group.Terminal)
{
this.BaseCost = new Cost(6);
this.Text = "Trash a card from your hand.Gain a card costing up to 5.";
}
public override void Play(Player player)
{
base.Play(player);
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));
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost <= new Coin(5));
Choice choice = new Choice("Gain a card costing up to 5", this, gainableSupplies, player, false);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply);
}
}
public class Armory : Card
{
public Armory()
: base("Armory", Category.Action, Source.DarkAges, Location.Kingdom, Group.Gain | Group.CardOrdering | Group.Terminal)
{
this.BaseCost = new Cost(4);
this.Text = "Gain a card costing up to 4, putting it on top of your deck.";
}
public override void Play(Player player)
{
base.Play(player);
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost <= new Coin(4));
Choice choice = new Choice("Gain a card costing up to 4", this, gainableSupplies, player, false);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply, DeckLocation.Deck, DeckPosition.Top);
}
}
public class BandOfMisfits : Card
{
public BandOfMisfits()
: base("Band of Misfits", Category.Action, Source.DarkAges, Location.Kingdom)
{
this.BaseCost = new Cost(5);
this.Text = "Play this as if it were an Action card in the Supply costing less than it that you choose.This is that card until it leaves play.";
}
}
public class BanditCamp : Card
{
public BanditCamp()
: base("Bandit Camp", Category.Action, Source.DarkAges, Location.Kingdom, Group.Gain | Group.PlusCard | Group.PlusAction | Group.PlusMultipleActions)
{
this.BaseCost = new Cost(5);
this.Benefit.Cards = 1;
this.Benefit.Actions = 2;
this.Text = "Gain a Spoils from the Spoils pile.";
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
if (!game.Table.SpecialPiles.ContainsKey(TypeClass.Spoils))
{
Supply spoilsSupply = new Supply(game, game.Players, TypeClass.Spoils, Spoils.BaseCount);
spoilsSupply.Setup();
game.Table.SpecialPiles.Add(TypeClass.Spoils, spoilsSupply);
}
}
public override void Play(Player player)
{
base.Play(player);
player.Gain(player._Game.Table.SpecialPiles[TypeClass.Spoils]);
}
}
public class Beggar : Card
{
private Player.AttackedEventHandler _AttackHandler = null;
public Beggar()
: base("Beggar", Category.Action | Category.Reaction, Source.DarkAges, Location.Kingdom, Group.Gain | Group.ReactToAttack | Group.CardOrdering | Group.Terminal)
{
this.BaseCost = new Cost(2);
this.Text = "Gain 3 Coppers, putting them into your hand.
When another player plays an Attack card, you may discard this. If you do, gain two Silvers, putting one on top of your deck.";
}
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.Beggar))
e.Revealable[TypeClass.Beggar] = new AttackReaction(this, String.Format("Discard {0}", this), player_RevealBeggar);
}
internal void player_RevealBeggar(Player player, ref AttackedEventArgs e)
{
player.Discard(DeckLocation.Hand, this);
player.Gain(player._Game.Table.Silver, DeckLocation.Deck, DeckPosition.Top);
player.Gain(player._Game.Table.Silver);
e.HandledBy.Add(TypeClass.Beggar);
// Attack isn't cancelled... it's just mitigated
}
public override void RemovedFrom(DeckLocation location, Player player)
{
base.RemovedFrom(location, player);
if (_AttackHandler != null)
player.Attacked -= _AttackHandler;
_AttackHandler = null;
}
public override void Play(Player player)
{
base.Play(player);
player.Gain(player._Game.Table.Copper, DeckLocation.Hand, DeckPosition.Automatic, 3);
}
}
public class Catacombs : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public Catacombs()
: base("Catacombs", Category.Action, Source.DarkAges, Location.Kingdom, Group.CardOrdering | Group.ReactToTrashing | Group.Gain | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(5);
this.Text = "Look at the top 3 cards of your deck. Choose one: Put them into your hand; or discard them and +3 Cards.
When you trash this, gain a cheaper card.";
this.OwnerChanged += new OwnerChangedEventHandler(Catacombs_OwnerChanged);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Catacombs_OwnerChanged);
}
void Catacombs_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.Catacombs) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.Catacombs] = new TrashAction(this.Owner, this, "Gain a cheaper card", player_PlusCard, true);
}
internal void player_PlusCard(Player player, ref TrashEventArgs e)
{
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost < player._Game.Cost(this));
Choice choice = new Choice(String.Format("Gain a card costing less than {0}", player._Game.Cost(this).ToString()), this, gainableSupplies, player, false);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply);
e.HandledBy.Add(this);
}
public override void Play(Player player)
{
base.Play(player);
CardCollection newCards = player.Draw(3, DeckLocation.Private);
Choice choice = new Choice(
String.Format("Do you want to discard {0} or put them back on top?", String.Join(" and ", newCards.Select(c => c.Name))),
this,
newCards,
new List() { "Discard", "Put them into your hand" },
player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options[0] == "Discard")
{
player.Discard(DeckLocation.Private);
player.DrawHand(3);
}
else
{
player.AddCardsToHand(DeckLocation.Private);
}
}
}
public class Count : Card
{
public Count()
: base("Count", Category.Action, Source.DarkAges, Location.Kingdom, Group.CardOrdering | Group.Discard | Group.Gain | Group.PlusCoin | Group.Trash | Group.Terminal)
{
this.BaseCost = new Cost(5);
this.Text = "Choose one: Discard 2 cards; or put a card from your hand on top of your deck; or gain a Copper.Choose one: +3; or trash your hand; or gain a Duchy.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choiceTheFirst = new Choice("Choose one:", this, new CardCollection() { this }, new List() { "Discard 2 cards", "Put a card on your deck", "Gain a Copper" }, player);
ChoiceResult resultTheFirst = player.MakeChoice(choiceTheFirst);
if (resultTheFirst.Options.Contains("Discard 2 cards"))
{
Choice choiceDiscard = new Choice("Discard 2 cards.", this, player.Hand, player, false, 2, 2);
ChoiceResult resultDiscard = player.MakeChoice(choiceDiscard);
player.Discard(DeckLocation.Hand, resultDiscard.Cards);
}
else if (resultTheFirst.Options.Contains("Put a card on your deck"))
{
Choice replaceChoice = new Choice("Choose a card to put back on your deck", this, player.Hand, player, false, 1, 1);
ChoiceResult replaceResult = player.MakeChoice(replaceChoice);
player.RetrieveCardsFrom(DeckLocation.Hand, replaceResult.Cards);
player.AddCardsToDeck(replaceResult.Cards, DeckPosition.Top);
}
else
{
player.Gain(player._Game.Table.Copper);
}
Choice choiceTheSecond = new Choice("Choose one:", this, new CardCollection() { this }, new List() { "+3", "Trash your hand", "Gain a Duchy" }, player);
ChoiceResult resultTheSecond = player.MakeChoice(choiceTheSecond);
if (resultTheSecond.Options.Contains("+3"))
{
player.ReceiveBenefit(this, new CardBenefit() { Currency = new Currency(3) });
}
else if (resultTheSecond.Options.Contains("Trash your hand"))
{
player.Trash(player.RetrieveCardsFrom(DeckLocation.Hand));
}
else
{
player.Gain(player._Game.Table.Duchy);
}
}
}
public class Counterfeit : Card
{
public Counterfeit()
: base("Counterfeit", Category.Treasure, Source.DarkAges, Location.Kingdom, Group.PlusCoin | Group.PlusBuy | Group.Trash)
{
this.BaseCost = new Cost(5);
this.Benefit.Currency.Coin.Value = 1;
this.Benefit.Buys = 1;
this.Text = "When you play this, you may play a Treasure from your hand twice. If you do, trash that Treasure.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choice = new Choice(String.Format("You may play a Treasure card twice", player), this, player.Hand[Cards.Category.Treasure], player, false, 0, 1);
ChoiceResult result = player.MakeChoice(choice);
if (result.Cards.Count > 0)
{
Card card = result.Cards[0];
player.PlayCardInternal(card);
player.PlayCardInternal(card, " again");
if (player.Tableau.Contains(card))
player.Trash(player.RetrieveCardFrom(DeckLocation.Tableau, card));
}
else
player.PlayNothing();
}
}
public class Cultist : Looter
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public Cultist()
: base("Cultist", Category.Action | Category.Attack, Group.Gain | Group.ReactToTrashing)
{
this.BaseCost = new Cost(5);
this.Benefit.Cards = 2;
this.Text = "Each other player gains a Ruins. You may play a Cultist from your hand.
When you trash this, +3 Cards.";
this.OwnerChanged += new OwnerChangedEventHandler(Cultist_OwnerChanged);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Cultist_OwnerChanged);
}
void Cultist_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.Cultist) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.Cultist] = new TrashAction(this.Owner, this, "+3 Cards", player_PlusCard, true);
}
internal void player_PlusCard(Player player, ref TrashEventArgs e)
{
player.ReceiveBenefit(this, new CardBenefit() { Cards = 3 });
e.HandledBy.Add(this);
}
public override void Play(Player player)
{
Dictionary attackSuccess = new Dictionary();
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext();
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
// Skip if the attack is blocked (Moat, Lighthouse, etc.)
attackSuccess[attackee] = attackee.AttackedBy(player, this);
}
base.Play(player);
enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext();
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
if (!attackSuccess[attackee])
continue;
attackee.Gain(player._Game.Table[TypeClass.RuinsSupply]);
}
if (player.Hand[TypeClass.Cultist].Count > 0)
{
Choice choicePlayer = Choice.CreateYesNoChoice("Do you want to play a Cultist from your hand?", this, player);
ChoiceResult resultPlayer = player.MakeChoice(choicePlayer);
if (resultPlayer.Options[0] == "Yes")
{
player.Actions++;
player.PlayCardInternal(player.Hand[TypeClass.Cultist][0]);
}
}
}
}
public class DameAnna : Knight
{
public DameAnna()
: base("Dame Anna", Category.Action | Category.Attack | Category.Knight, Group.Terminal | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Text = "You may trash up to 2 cards from your hand.Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
Choice choiceTrash = new Choice("Choose up to 2 cards to trash", this, player.Hand, player, false, 0, 2);
ChoiceResult resultTrash = player.MakeChoice(choiceTrash);
player.Trash(player.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards));
this.KnightAttack(player);
}
}
public class DameJosephine : Knight
{
public DameJosephine()
: base("Dame Josephine", Category.Action | Category.Attack | Category.Knight | Category.Victory, Group.Terminal | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.VictoryPoints = 2;
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class DameMolly : Knight
{
public DameMolly()
: base("Dame Molly", Category.Action | Category.Attack | Category.Knight, Group.PlusAction | Group.PlusMultipleActions | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Benefit.Actions = 2;
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class DameNatalie : Knight
{
public DameNatalie()
: base("Dame Natalie", Category.Action | Category.Attack | Category.Knight, Group.Terminal | Group.Trash | Group.Discard | Group.Gain)
{
this.BaseCost = new Cost(5);
this.Text = "You may gain a card costing up to 3.Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost <= new Coin(3));
Choice choice = new Choice("You may gain a card costing up to 3", this, gainableSupplies, player, true);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply);
this.KnightAttack(player);
}
}
public class DameSylvia : Knight
{
public DameSylvia()
: base("Dame Sylvia", Category.Action | Category.Attack | Category.Knight, Group.PlusCoin | Group.Terminal | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Benefit.Currency.Coin.Value = 2;
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class DeathCart : Looter
{
private Dictionary _CardGainedHandlers = new Dictionary();
public DeathCart()
: base("Death Cart", Category.Action, Group.PlusCoin | Group.Trash | Group.Gain | Group.Terminal)
{
this.BaseCost = new Cost(4);
this.Benefit.Currency.Coin.Value = 5;
this.Text = "You may trash an Action card from your hand. If you don't, trash this.
When you gain this, gain 2 Ruins.";
}
internal override void TearDown()
{
base.TearDown();
foreach (Player playerLoop in _CardGainedHandlers.Keys)
playerLoop.CardGained -= _CardGainedHandlers[playerLoop];
_CardGainedHandlers.Clear();
}
public override void AddedToSupply(Game game, Supply supply)
{
base.AddedToSupply(game, supply);
ResetTriggers(game);
}
internal override void TrashedBy(Player player)
{
base.TrashedBy(player);
// Need to reset any Gain triggers when we're trashed -- we can technically be gained from the Trash
ResetTriggers(player._Game);
}
private void ResetTriggers(Game game)
{
IEnumerator enumPlayers = game.GetPlayersStartingWithActiveEnumerator();
while (enumPlayers.MoveNext())
{
_CardGainedHandlers[enumPlayers.Current] = new Player.CardGainedEventHandler(player_CardGained);
enumPlayers.Current.CardGained += _CardGainedHandlers[enumPlayers.Current];
}
}
void player_CardGained(object sender, Players.CardGainEventArgs e)
{
// This is not the card you are looking for
if (e.Card != this || e.Actions.ContainsKey(TypeClass.DeathCart) || !e.Game.Table.Copper.CanGain())
return;
Player player = sender as Player;
e.Actions[TypeClass.DeathCart] = new Players.CardGainAction(this.Owner, this, "Gain 2 Ruins", player_GainCache, true);
}
internal void player_GainCache(Player player, ref Players.CardGainEventArgs e)
{
player.Gain(player._Game.Table[TypeClass.RuinsSupply], 2);
e.HandledBy.Add(TypeClass.DeathCart);
// Clear out the Event Triggers -- this only happens when its Gained, so we don't care any more
foreach (Player playerLoop in _CardGainedHandlers.Keys)
playerLoop.CardGained -= _CardGainedHandlers[playerLoop];
_CardGainedHandlers.Clear();
}
public override void Play(Player player)
{
base.Play(player);
Choice choiceTrash = new Choice("You may trash an Action card", this, player.Hand[Cards.Category.Action], player, false, 0, 1);
ChoiceResult resultTrash = player.MakeChoice(choiceTrash);
if (resultTrash.Cards.Count > 0)
{
player.Trash(player.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards));
}
else if (player.Tableau.Contains(this))
{
player.Trash(player.RetrieveCardFrom(DeckLocation.Tableau, this));
}
}
}
public class Feodum : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public Feodum()
: base("Feodum", Category.Victory, Source.DarkAges, Location.Kingdom, Group.ReactToTrashing | Group.VariableVPs)
{
this.BaseCost = new Cost(4);
this.Text = "Worth 1 for every 3 Silvers in your deck (rounded down).
When you trash this, gain 3 Silvers.";
this.OwnerChanged += new OwnerChangedEventHandler(Feodum_OwnerChanged);
}
public override int GetVictoryPoints(IEnumerable cards)
{
return base.GetVictoryPoints(cards) +
cards.Count(c => c.CardType == Cards.Universal.TypeClass.Silver) / 3;
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Feodum_OwnerChanged);
}
void Feodum_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.Feodum) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.Feodum] = new TrashAction(this.Owner, this, "Gain 3 Silvers", player_Gain3Silvers, true);
}
internal void player_Gain3Silvers(Player player, ref TrashEventArgs e)
{
player.Gain(player._Game.Table.Silver, 3);
e.HandledBy.Add(this);
}
}
public class Forager : Card
{
public Forager()
: base("Forager", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusAction | Group.PlusBuy | Group.Trash | Group.PlusCoin)
{
this.BaseCost = new Cost(3);
this.Benefit.Actions = 1;
this.Benefit.Buys = 1;
this.Text = "Trash a card from your hand.+1 per differently named Treasure in the trash.";
}
public override void Play(Player player)
{
base.Play(player);
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));
player.ReceiveBenefit(this, new CardBenefit()
{
Currency = new Currency(player._Game.Table.Trash.Where(card =>
(card.Category & Cards.Category.Treasure) == Cards.Category.Treasure
).GroupBy(card => card.Name).Count())
});
}
}
public class Fortress : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
private Player.TrashedFinishedEventHandler _TrashedFinishedEventHandler = null;
public Fortress()
: base("Fortress", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.PlusMultipleActions | Group.ReactToTrashing)
{
this.BaseCost = new Cost(4);
this.Benefit.Cards = 1;
this.Benefit.Actions = 2;
this.Text = "
When you trash this, put it into your hand.";
this.OwnerChanged += new OwnerChangedEventHandler(Fortress_OwnerChanged);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Fortress_OwnerChanged);
}
void Fortress_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.Fortress) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.Fortress] = new TrashAction(this.Owner, this, "Put Fortress into your hand", player_RegainFortress, true);
}
void player_TrashedFinished(object sender, TrashEventArgs e)
{
this.ObtainedBy(e.CurrentPlayer);
if (_TrashedFinishedEventHandler != null)
e.CurrentPlayer.TrashedFinished -= _TrashedFinishedEventHandler;
_TrashedFinishedEventHandler = null;
}
internal void player_RegainFortress(Player player, ref TrashEventArgs e)
{
if (player._Game.Table.Trash.Contains(this))
{
player.Gain(player._Game.Table.Trash, this, DeckLocation.Hand, DeckPosition.Automatic);
_TrashedFinishedEventHandler = new Player.TrashedFinishedEventHandler(player_TrashedFinished);
player.TrashedFinished += _TrashedFinishedEventHandler;
}
e.HandledBy.Add(this);
}
}
public class Graverobber : Card
{
public Graverobber()
: base("Graverobber", Category.Action, Source.DarkAges, Location.Kingdom, Group.DeckReduction | Group.Gain | Group.RemoveCurses | Group.Terminal | Group.Trash)
{
this.BaseCost = new Cost(5);
this.Text = "Choose one: Gain a card from the trash costing from 3 to 6, putting it on top of your deck; or trash an Action card from your hand and gain a card costing up to 3 more than it.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choice = new Choice("Choose one:", this, new CardCollection() { this }, new List() { "Gain a card from the trash", "Trash an Action card from your hand" }, player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options.Contains("Gain a card from the trash"))
{
List availableCosts = new List() { new Cost(3), new Cost(4), new Cost(5), new Cost(6) };
IEnumerable availableTrashCards = player._Game.Table.Trash.Where(c => availableCosts.Any(cost => player._Game.Cost(c) == cost));
Choice choiceFromTrash = new Choice("Choose a card to gain from the trash", this, availableTrashCards, player);
ChoiceResult resultFromTrash = player.MakeChoice(choiceFromTrash);
if (resultFromTrash.Cards.Count > 0)
{
player.Gain(player._Game.Table.Trash, resultFromTrash.Cards[0], DeckLocation.Deck, DeckPosition.Top);
}
}
else
{
Choice choiceTrash = new Choice("Choose an Action card to trash", this, player.Hand[Cards.Category.Action], 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(3)));
Choice choiceGain = new Choice("Gain a card", this, gainableSupplies, player, false);
ChoiceResult resultGain = player.MakeChoice(choiceGain);
if (resultGain.Supply != null)
player.Gain(resultGain.Supply);
}
}
}
}
public class Hermit : Card
{
private Player.CardsDiscardingEventHandler _CardsDiscardingEventHandler = null;
public Hermit()
: base("Hermit", Category.Action, Source.DarkAges, Location.Kingdom, Group.Gain | Group.Terminal | Group.Trash)
{
this.BaseCost = new Cost(3);
this.Text = "Look through your discard pile. You may trash a card from your discard pile or hand that is not a Treasure. Gain a card costing up to 3.
When you discard this from play, if you did not buy any cards this turn, trash this and gain a Madman from the Madman pile.";
this.OwnerChanged += new OwnerChangedEventHandler(Hermit_OwnerChanged);
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
Supply madmanSupply = new Supply(game, game.Players, TypeClass.Madman, 10);
madmanSupply.Setup();
game.Table.SpecialPiles.Add(TypeClass.Madman, madmanSupply);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Hermit_OwnerChanged);
}
void Hermit_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_CardsDiscardingEventHandler != null && e.OldOwner != null)
{
e.OldOwner.CardsDiscarding -= _CardsDiscardingEventHandler;
_CardsDiscardingEventHandler = null;
}
if (e.NewOwner != null)
{
_CardsDiscardingEventHandler = new Player.CardsDiscardingEventHandler(player_CardsDiscarding);
e.NewOwner.CardsDiscarding += _CardsDiscardingEventHandler;
}
}
void player_CardsDiscarding(object sender, CardsDiscardEventArgs e)
{
if (!e.Cards.Contains(this) || e.Actions.ContainsKey(TypeClass.Hermit) || e.HandledBy.Contains(this) ||
(e.FromLocation != DeckLocation.Tableau && e.FromLocation != DeckLocation.PreviousTableau))
return;
// Only allow this if no cards were bought this turn
if (((sender as Player).CurrentTurn.CardsBought.Count) == 0)
e.Actions[TypeClass.Hermit] = new CardsDiscardAction(sender as Player, this, String.Format("Trash {0}", this), player_Action, true);
}
internal void player_Action(Player player, ref CardsDiscardEventArgs e)
{
e.Cards.Remove(this);
if (player.Tableau.Contains(this))
player.RetrieveCardFrom(DeckLocation.Tableau, this);
else
player.RetrieveCardFrom(DeckLocation.PreviousTableau, this);
player.Trash(this);
player.Gain(player._Game.Table.SpecialPiles[TypeClass.Madman]);
e.HandledBy.Add(this);
}
public override void Play(Player player)
{
base.Play(player);
CardCollection nonTreasures = player.DiscardPile.LookThrough(c => (c.Category & Cards.Category.Treasure) != Cards.Category.Treasure);
nonTreasures.Add(new Universal.Dummy());
nonTreasures.AddRange(player.Hand[c => (c.Category & Cards.Category.Treasure) != Cards.Category.Treasure]);
if (nonTreasures.Count > 1)
{
Choice choiceTrash = new Choice("You may choose a non-Treasure card to trash", this, nonTreasures, player, false, 0, 1);
ChoiceResult resultTrash = player.MakeChoice(choiceTrash);
if (resultTrash.Cards.Count > 0)
{
Card cardToTrash = null;
if (player.Hand.Contains(resultTrash.Cards[0]))
cardToTrash = player.RetrieveCardFrom(DeckLocation.Hand, resultTrash.Cards[0]);
else
cardToTrash = player.RetrieveCardFrom(DeckLocation.Discard, resultTrash.Cards[0]);
player.Trash(cardToTrash);
}
}
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost <= new Coin(3));
Choice choice = new Choice("Gain a card costing up to 3", this, gainableSupplies, player, false);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply);
}
}
public class Hovel : Card
{
private Player.CardBoughtEventHandler _CardBoughtEventHandler = null;
public Hovel()
: base("Hovel", Category.Reaction | Category.Shelter, Source.DarkAges, Location.General, Group.ReactToTrashing)
{
this.BaseCost = new Cost(1);
this.Text = "When you buy a Victory card, you may trash this from your hand.";
}
public override void AddedTo(DeckLocation location, Player player)
{
base.AddedTo(location, player);
if (location == DeckLocation.Hand)
{
_CardBoughtEventHandler = new Player.CardBoughtEventHandler(player_CardBought);
player.CardBought += _CardBoughtEventHandler;
}
}
void player_CardBought(object sender, Players.CardBuyEventArgs e)
{
Player player = sender as Player;
// Already been cancelled -- don't need to process this one
if (e.Cancelled || !player.Hand.Contains(this) || e.Actions.ContainsKey(TypeClass.Hovel))
return;
if ((e.Card.Category & Cards.Category.Victory) == Cards.Category.Victory)
e.Actions[TypeClass.Hovel] = new Players.CardBuyAction(this.Owner, this, String.Format("Trash {0}", this), player_TrashHovel, false);
}
internal void player_TrashHovel(Player player, ref Players.CardBuyEventArgs e)
{
player.Trash(player.RetrieveCardFrom(DeckLocation.Hand, this));
e.HandledBy.Add(this);
}
public override void RemovedFrom(DeckLocation location, Player player)
{
base.RemovedFrom(location, player);
if (_CardBoughtEventHandler != null)
player.CardBought -= _CardBoughtEventHandler;
_CardBoughtEventHandler = null;
}
}
public class HuntingGrounds : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public HuntingGrounds()
: base("Hunting Grounds", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.ReactToTrashing | Group.Terminal | Group.Gain)
{
this.BaseCost = new Cost(6);
this.Benefit.Cards = 4;
this.Text = "
When you trash this, gain a Duchy or 3 Estates.";
this.OwnerChanged += new OwnerChangedEventHandler(HuntingGrounds_OwnerChanged);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(HuntingGrounds_OwnerChanged);
}
void HuntingGrounds_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.HuntingGrounds) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.HuntingGrounds] = new TrashAction(this.Owner, this, "Gain Duchy/Estates", player_PlusCard, true);
}
internal void player_PlusCard(Player player, ref TrashEventArgs e)
{
Choice choice = new Choice("Choose one:", this, new CardCollection() { this }, new List() { "Gain a Duchy", "Gain 3 Estates" }, player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options.Contains("Gain a Duchy"))
{
player.Gain(player._Game.Table.Duchy);
}
else
{
player.Gain(player._Game.Table.Estate, 3);
}
e.HandledBy.Add(this);
}
}
public class Ironmonger : Card
{
public Ironmonger()
: base("Ironmonger", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.Discard | Group.CardOrdering | Group.PlusMultipleActions | Group.PlusCoin)
{
this.BaseCost = new Cost(4);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Text = "Reveal the top card of your deck;you may discard it.Either way, if it is an...Action card, +1 ActionTreasure card, +1Victory card, +1 Card";
}
public override void Play(Player player)
{
base.Play(player);
Card revealedCard = player.Draw(DeckLocation.Revealed);
if (revealedCard != null)
{
Choice choice = new Choice(
String.Format("Do you want to discard {0} or put it back on your deck?", revealedCard),
this,
new CardCollection() { this },
new List() { "Discard", "Put it back" },
player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options.Contains("Discard"))
player.DiscardRevealed();
else
player.AddCardsToDeck(player.RetrieveCardsFrom(DeckLocation.Revealed), DeckPosition.Top);
CardBenefit benefit = new CardBenefit();
if ((revealedCard.Category & Cards.Category.Action) == Cards.Category.Action)
benefit.Actions = 1;
if ((revealedCard.Category & Cards.Category.Treasure) == Cards.Category.Treasure)
benefit.Currency += new Coin(1);
if ((revealedCard.Category & Cards.Category.Victory) == Cards.Category.Victory)
benefit.Cards = 1;
player.ReceiveBenefit(this, benefit);
}
}
}
public class JunkDealer : Card
{
public JunkDealer()
: base("Junk Dealer", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.PlusCoin | Group.Trash | Group.DeckReduction)
{
this.BaseCost = new Cost(5);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Benefit.Currency.Coin.Value = 1;
this.Text = "Trash a card from your hand.";
}
public override void Play(Player player)
{
base.Play(player);
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));
}
}
public abstract class Knight : Card
{
internal Knight(String name, Category category, Group group)
: base(name, category, Source.DarkAges, Location.Special, group)
{
}
public void KnightAttack(Player player)
{
List availableCosts = new List() { new Cost(3), new Cost(4), new Cost(5), new Cost(6) };
Boolean anyKnightsTrashed = false;
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext();
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
if (this.IsAttackBlocked[attackee])
continue;
CardCollection attackeeCards = attackee.Draw(2, DeckLocation.Revealed);
Choice choiceTrash = new Choice("Choose a card to trash", this, attackee.Revealed[c => availableCosts.Any(cost => player._Game.Cost(c) == cost)], player);
ChoiceResult resultTrash = attackee.MakeChoice(choiceTrash);
if (resultTrash.Cards.Count > 0)
{
Card cardToTrash = attackee.RetrieveCardFrom(DeckLocation.Revealed, resultTrash.Cards[0]);
if ((cardToTrash.Category & Cards.Category.Knight) == Cards.Category.Knight)
anyKnightsTrashed = true;
attackee.Trash(cardToTrash);
}
attackee.DiscardRevealed();
}
if (anyKnightsTrashed)
player.Trash(player.RetrieveCardFrom(DeckLocation.Tableau, this));
}
}
public class Knights : Card
{
public Knights()
: base("Knights", Category.Action | Category.Attack | Category.Knight, Source.DarkAges, Location.Kingdom, Group.None)
{
this.BaseCost = new Cost(5);
this.Text = "Shuffle the Knight pile before each game with it. Keep it face down except for the top card, which is the only one that can be bought or gained.";
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
supply.Empty();
CardCollection cards = new CardCollection();
cards.Add(new DameAnna());
cards.Add(new DameJosephine());
cards.Add(new DameMolly());
cards.Add(new DameNatalie());
cards.Add(new DameSylvia());
cards.Add(new SirBailey());
cards.Add(new SirDestry());
cards.Add(new SirMartin());
cards.Add(new SirMichael());
cards.Add(new SirVander());
Utilities.Shuffler.Shuffle(cards);
supply.AddTo(cards);
}
}
public abstract class Looter : Card
{
internal Looter(String name, Category category, Group group)
: base(name, category | Category.Looter, Source.DarkAges, Location.Kingdom, group)
{
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
if (!game.Table.Supplies.ContainsKey(TypeClass.RuinsSupply))
{
Supply ruinsSupply = new Supply(game, game.Players, TypeClass.RuinsSupply, Visibility.Top);
ruinsSupply.Setup();
game.Table.Supplies.Add(TypeClass.RuinsSupply, ruinsSupply);
}
}
}
public class Madman : Card
{
public Madman()
: base("Madman", Category.Action, Source.DarkAges, Location.Special, Group.DeckReduction | Group.PlusAction | Group.PlusCard | Group.PlusMultipleActions)
{
this.BaseCost = new Cost(0, true);
this.Benefit.Actions = 2;
this.Text = "Return this to the Madman pile. If you do, +1 Card per card in your hand.(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
if (player.Tableau.Contains(this))
{
Supply supply = player._Game.Table.SpecialPiles[TypeClass.Madman];
Card cardToReturn = player.RetrieveCardFrom(DeckLocation.Tableau, this);
player.Lose(this);
supply.AddTo(this);
player._Game.SendMessage(player, this, supply, 1);
player.ReceiveBenefit(this, new CardBenefit() { Cards = player.Hand.Count });
}
}
}
public class Marauder : Looter
{
public Marauder()
: base("Marauder", Category.Action | Category.Attack, Group.Gain)
{
this.BaseCost = new Cost(4);
this.Text = "Gain a Spoils from the Spoils pile.Each other player gains a Ruins.";
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
if (!game.Table.SpecialPiles.ContainsKey(TypeClass.Spoils))
{
Supply spoilsSupply = new Supply(game, game.Players, TypeClass.Spoils, Spoils.BaseCount);
spoilsSupply.Setup();
game.Table.SpecialPiles.Add(TypeClass.Spoils, spoilsSupply);
}
}
public override void Play(Player player)
{
base.Play(player);
player.Gain(player._Game.Table.SpecialPiles[TypeClass.Spoils]);
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[TypeClass.RuinsSupply]);
}
}
}
public class MarketSquare : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public MarketSquare()
: base("Market Square", Category.Action | Category.Reaction, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.PlusBuy | Group.ReactToTrashing | Group.Discard | Group.Gain)
{
this.BaseCost = new Cost(3);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Benefit.Buys = 1;
this.Text = "
When one of your cards is trashed, you may discard this from your hand. If you do, gain a Gold.";
}
public override void AddedTo(DeckLocation location, Player player)
{
base.AddedTo(location, player);
if (location == DeckLocation.Hand)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
player.Trashed += _TrashedEventHandler;
}
}
public override void RemovedFrom(DeckLocation location, Player player)
{
base.RemovedFrom(location, player);
if (_TrashedEventHandler != null)
player.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.MarketSquare) || e.HandledBy.Contains(this))
return;
e.Actions[TypeClass.MarketSquare] = new TrashAction(this.Owner, this, "Discard Market Square", player_DiscardMarketSquare, false);
}
internal void player_DiscardMarketSquare(Player player, ref TrashEventArgs e)
{
player.Discard(DeckLocation.Hand, this);
player.Gain(player._Game.Table.Gold);
e.HandledBy.Add(this);
}
}
public class Mercenary : Card
{
public const int BaseCount = 10;
public Mercenary()
: base("Mercenary", Category.Action | Category.Attack, Source.DarkAges, Location.Special, Group.PlusCard | Group.PlusCoin | Group.Trash | Group.DeckReduction)
{
this.BaseCost = new Cost(0, true);
this.Text = "You may trash 2 cards from your hand.If you do, +2 Cards, +2, and each other player discards down to 3 cards in hand.(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
Choice choice = Choice.CreateYesNoChoice("Do you want to trash 2 cards?", this, player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options[0] == "Yes")
{
Choice choiceTrash = new Choice("Choose 2 cards to trash", this, player.Hand, player, false, 2, 2);
ChoiceResult resultTrash = player.MakeChoice(choiceTrash);
player.Trash(player.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards));
if (resultTrash.Cards.Count == 2)
{
player.ReceiveBenefit(this, new CardBenefit() { Cards = 2, Currency = new Currency(2) });
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;
Choice choiceDiscard = 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 resultDiscard = attackee.MakeChoice(choiceDiscard);
attackee.Discard(DeckLocation.Hand, resultDiscard.Cards);
}
}
}
}
}
public class Mystic : Card
{
public Mystic()
: base("Mystic", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusAction | Group.PlusCoin | Group.PlusCard)
{
this.BaseCost = new Cost(5);
this.Benefit.Actions = 1;
this.Benefit.Currency.Coin.Value = 2;
this.Text = "Name a card.Reveal the top card of your deck.If it's the named card, put it into your hand.";
}
public override void Play(Player player)
{
base.Play(player);
SupplyCollection availableSupplies = new SupplyCollection(player._Game.Table.Supplies.Where(kvp => kvp.Value.Randomizer != null && kvp.Value.Randomizer.GroupMembership != Group.None));
CardCollection cards = new CardCollection();
Choice choice = new Choice("Name a card", this, availableSupplies, player, false);
foreach (Supply supply in player._Game.Table.Supplies.Values.Union(player._Game.Table.SpecialPiles.Values))
{
foreach (Type type in supply.CardTypes)
{
if (!choice.Supplies.Any(kvp => kvp.Value.CardType == type))
cards.Add(Card.CreateInstance(type));
}
}
choice.AddCards(cards);
ChoiceResult result = player.MakeChoice(choice);
ICard namedCard = null;
if (result.Supply != null)
namedCard = result.Supply;
else
namedCard = result.Cards[0];
player._Game.SendMessage(player, this, namedCard);
player.Draw(DeckLocation.Revealed);
if (player.Revealed[namedCard.CardType].Count > 0)
{
player.AddCardsToHand(DeckLocation.Revealed);
}
else
{
player.AddCardsToDeck(player.RetrieveCardsFrom(DeckLocation.Revealed), DeckPosition.Top);
}
}
}
public class Necropolis : Card
{
public Necropolis()
: base("Necropolis", Category.Action | Category.Shelter, Source.DarkAges, Location.General, Group.PlusAction | Group.PlusMultipleActions)
{
this.BaseCost = new Cost(1);
this.Benefit.Actions = 2;
}
}
public class OvergrownEstate : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public OvergrownEstate()
: base("Overgrown Estate", Category.Victory | Category.Shelter, Source.DarkAges, Location.General, Group.ReactToTrashing)
{
this.BaseCost = new Cost(1);
this.Benefit.VictoryPoints = 0;
this.Text = "
When you trash this, +1 Card";
this.OwnerChanged += new OwnerChangedEventHandler(OvergrownEstate_OwnerChanged);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(OvergrownEstate_OwnerChanged);
}
void OvergrownEstate_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.OvergrownEstate) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.OvergrownEstate] = new TrashAction(this.Owner, this, "+1 Card", player_PlusCard, true);
}
internal void player_PlusCard(Player player, ref TrashEventArgs e)
{
player.ReceiveBenefit(this, new CardBenefit() { Cards = 1 });
e.HandledBy.Add(this);
}
}
public class Pillage : Card
{
public Pillage()
: base("Pillage", Category.Action | Category.Attack, Source.DarkAges, Location.Kingdom, Group.Discard | Group.Gain | Group.Terminal | Group.Trash)
{
this.BaseCost = new Cost(5);
this.Text = "Trash this. Each other player with 5 or more cards in hand reveals his hand and discards a card you choose.Gain 2 Spoils from the Spoils pile.";
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
if (!game.Table.SpecialPiles.ContainsKey(TypeClass.Spoils))
{
Supply spoilsSupply = new Supply(game, game.Players, TypeClass.Spoils, Spoils.BaseCount);
spoilsSupply.Setup();
game.Table.SpecialPiles.Add(TypeClass.Spoils, spoilsSupply);
}
}
public override void Play(Player player)
{
base.Play(player);
if (player.Tableau.Contains(this))
{
player.RetrieveCardFrom(DeckLocation.Tableau, this);
player.Trash(this);
}
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;
if (attackee.Hand.Count < 5)
continue;
attackee.RevealHand();
Choice choice = new Choice(String.Format("Choose a card for {0} to discard.", attackee), this, attackee.Revealed, attackee, false, 1, 1);
ChoiceResult result = player.MakeChoice(choice);
attackee.Discard(DeckLocation.Revealed, result.Cards);
attackee.ReturnHand(attackee.Revealed[c => true]);
}
player.Gain(player._Game.Table.SpecialPiles[TypeClass.Spoils], 2);
}
}
public class PoorHouse : Card
{
public PoorHouse()
: base("Poor House", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCoin | Group.Terminal)
{
this.BaseCost = new Cost(1);
this.Benefit.Currency = new Currency(4);
this.Text = "Reveal your hand. -1 per Treasure card in your hand, to a minimum of 0.";
}
public override void Play(Player player)
{
base.Play(player);
player.ReturnHand(player.RevealHand());
Currency negativeCurrency = new Currency(-Math.Min(player.Currency.Coin.Value, player.Hand[Cards.Category.Treasure].Count));
player.ReceiveBenefit(this, new CardBenefit() { Currency = negativeCurrency });
}
}
public class Procession : Card
{
public Procession()
: base("Procession", Category.Action, Source.DarkAges, Location.Kingdom, Group.Trash | Group.Gain)
{
this.BaseCost = new Cost(4);
this.Text = "You may play an Action card from your hand twice. Trash it. Gain an Action card costing exactly 1 more than it.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choice = new Choice(String.Format("You may play an Action card twice", player), this, player.Hand[Cards.Category.Action], player, false, 0, 1);
ChoiceResult result = player.MakeChoice(choice);
if (result.Cards.Count > 0)
{
Card card = result.Cards[0];
card.ModifiedBy = this;
player.Actions++;
player.PlayCardInternal(card);
player.Actions++;
player.PlayCardInternal(card, " again");
if (player.Tableau.Contains(card))
player.Trash(player.RetrieveCardFrom(DeckLocation.Tableau, card));
Cost trashedCardCost = player._Game.Cost(card);
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && (supply.Category & Cards.Category.Action) == Cards.Category.Action && supply.CurrentCost == (trashedCardCost + new Coin(1)));
Choice choiceGain = new Choice("Gain an Action card", this, gainableSupplies, player, false);
ChoiceResult resultGain = player.MakeChoice(choiceGain);
if (resultGain.Supply != null)
player.Gain(resultGain.Supply);
}
else
player.PlayNothing();
}
protected override void Modify(Player player, Card card)
{
base.Modify(player, card);
base.Modify(player, card);
}
}
public class Rats : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public Rats()
: base("Rats", Category.Action, Source.DarkAges, Location.Kingdom, Group.DeckReduction | Group.Gain | Group.PlusAction | Group.PlusCard | Group.ReactToTrashing | Group.RemoveCurses | Group.Trash)
{
this.BaseCost = new Cost(4);
this.Benefit.Actions = 1;
this.Benefit.Cards = 1;
this.Text = "Gain a Rats. Trash a card from your hand other than a Rats (or reveal a hand of all Rats).
When you trash this, +1 Card.";
this.OwnerChanged += new OwnerChangedEventHandler(Rats_OwnerChanged);
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
// Add 10 more cards to the Rats pile, bringing it to 20
supply.AddTo(10);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Rats_OwnerChanged);
}
void Rats_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.Rats) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.Rats] = new TrashAction(this.Owner, this, "+1 Card", player_PlusCard, true);
}
internal void player_PlusCard(Player player, ref TrashEventArgs e)
{
player.ReceiveBenefit(this, new CardBenefit() { Cards = 1 });
e.HandledBy.Add(this);
}
public override void Play(Player player)
{
base.Play(player);
player.Gain(player._Game.Table[TypeClass.Rats]);
CardCollection nonRats = player.Hand[c => c.CardType != TypeClass.Rats];
if (nonRats.Count > 0)
{
Choice choiceTrash = new Choice("Choose a non-Rats card to trash", this, nonRats, player);
ChoiceResult resultTrash = player.MakeChoice(choiceTrash);
player.Trash(player.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards));
}
else
{
player.ReturnHand(player.RevealHand());
}
}
}
public class Rebuild : Card
{
public Rebuild()
: base("Rebuild", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusAction | Group.Discard | Group.Trash | Group.Gain)
{
this.BaseCost = new Cost(5);
this.Benefit.Actions = 1;
this.Text = "Name a card. Reveal cards from the top of your deck until you reveal a Victory card that is not the named card. Discard the other cards. Trash the Victory card and gain a Victory card costing up to 3 more than it.";
}
public override void Play(Player player)
{
base.Play(player);
SupplyCollection availableSupplies = new SupplyCollection(player._Game.Table.Supplies.Where(kvp => kvp.Value.Randomizer != null && kvp.Value.Randomizer.GroupMembership != Group.None));
CardCollection cards = new CardCollection();
Choice choice = new Choice("Name a card", this, availableSupplies, player, false);
foreach (Supply supply in player._Game.Table.Supplies.Values.Union(player._Game.Table.SpecialPiles.Values))
{
foreach (Type type in supply.CardTypes)
{
if (!choice.Supplies.Any(kvp => kvp.Value.CardType == type))
cards.Add(Card.CreateInstance(type));
}
}
choice.AddCards(cards);
ChoiceResult result = player.MakeChoice(choice);
ICard namedCard = null;
if (result.Supply != null)
namedCard = result.Supply;
else
namedCard = result.Cards[0];
player._Game.SendMessage(player, this, namedCard);
Card foundCard = null;
player.BeginDrawing();
while (player.CanDraw)
{
player.Draw(DeckLocation.Revealed);
Card lastRevealed = player.Revealed.Last();
if ((lastRevealed.Category & Cards.Category.Victory) == Cards.Category.Victory &&
namedCard.Name != lastRevealed.Name)
{
foundCard = lastRevealed;
break;
}
}
player.EndDrawing();
if (foundCard != null)
foundCard = player.RetrieveCardFrom(DeckLocation.Revealed, foundCard);
player.DiscardRevealed();
if (foundCard != null)
{
player.Trash(foundCard);
Cost trashedCardCost = player._Game.Cost(foundCard);
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && (supply.Category & Cards.Category.Victory) == Cards.Category.Victory && supply.CurrentCost <= (trashedCardCost + new Coin(3)));
Choice choiceGain = new Choice("Gain a Victory card", this, gainableSupplies, player, false);
ChoiceResult resultGain = player.MakeChoice(choiceGain);
if (resultGain.Supply != null)
player.Gain(resultGain.Supply);
}
}
}
public class Rogue : Card
{
public Rogue()
: base("Rogue", Category.Action | Category.Attack, Source.DarkAges, Location.Kingdom, Group.PlusCoin | Group.Terminal | Group.Trash | Group.Discard | Group.Gain)
{
this.BaseCost = new Cost(5);
this.Benefit.Currency.Coin.Value = 2;
this.Text = "If there are any cards in the trash costing from 3 to 6, gain one of them. Otherwise, each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest.";
}
public override void Play(Player player)
{
base.Play(player);
List availableCosts = new List() { new Cost(3), new Cost(4), new Cost(5), new Cost(6) };
IEnumerable availableTrashCards = player._Game.Table.Trash.Where(c => availableCosts.Any(cost => player._Game.Cost(c) == cost));
if (availableTrashCards.Count() > 0)
{
Choice choiceFromTrash = new Choice("Choose a card to gain from the trash", this, availableTrashCards, player);
ChoiceResult resultFromTrash = player.MakeChoice(choiceFromTrash);
if (resultFromTrash.Cards.Count > 0)
{
player.Gain(player._Game.Table.Trash, resultFromTrash.Cards[0]);
}
}
else
{
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;
CardCollection attackeeCards = attackee.Draw(2, DeckLocation.Revealed);
Choice choiceTrash = new Choice("Choose a card to trash", this, attackee.Revealed[c => availableCosts.Any(cost => player._Game.Cost(c) == cost)], attackee);
ChoiceResult resultTrash = attackee.MakeChoice(choiceTrash);
attackee.Trash(attackee.RetrieveCardsFrom(DeckLocation.Revealed, resultTrash.Cards));
attackee.DiscardRevealed();
}
}
}
}
public class RuinedLibrary : Card
{
public RuinedLibrary()
: base("Ruined Library", Category.Action | Category.Ruins, Source.DarkAges, Location.General, Group.PlusCard | Group.Terminal)
{
this.BaseCost = new Cost(0);
this.Benefit.Cards = 1;
}
public override Type BaseType { get { return TypeClass.RuinsSupply; } }
}
public class RuinedMarket : Card
{
public RuinedMarket()
: base("Ruined Market", Category.Action | Category.Ruins, Source.DarkAges, Location.General, Group.PlusBuy | Group.Terminal)
{
this.BaseCost = new Cost(0);
this.Benefit.Buys = 1;
}
public override Type BaseType { get { return TypeClass.RuinsSupply; } }
}
public class RuinedVillage : Card
{
public RuinedVillage()
: base("Ruined Village", Category.Action | Category.Ruins, Source.DarkAges, Location.General, Group.PlusAction)
{
this.BaseCost = new Cost(0);
this.Benefit.Actions = 1;
}
public override Type BaseType { get { return TypeClass.RuinsSupply; } }
}
public class RuinsSupply : Card
{
public RuinsSupply()
: base("Ruins", Category.Ruins, Source.DarkAges, Location.General, Group.None)
{
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
CardCollection cards = new CardCollection();
for (int i = 0; i < 10; i++)
{
cards.Add(new AbandonedMine());
cards.Add(new RuinedLibrary());
cards.Add(new RuinedMarket());
cards.Add(new RuinedVillage());
cards.Add(new Survivors());
}
Utilities.Shuffler.Shuffle(cards);
supply.AddTo(cards.Take(10 * (game.Players.Count - 1)));
}
}
public class Sage : Card
{
public Sage()
: base("Sage", Category.Action, Source.DarkAges, Location.Kingdom, Group.Discard | Group.PlusAction | Group.PlusCard)
{
this.BaseCost = new Cost(3);
this.Benefit.Actions = 1;
this.Text = "Reveal cards from the top of your deck until you reveal one costing 3 or more. Put that card into your hand and discard the rest.";
}
public override void Play(Player player)
{
base.Play(player);
player.BeginDrawing();
while (player.CanDraw)
{
player.Draw(DeckLocation.Revealed);
if (player._Game.Cost(player.Revealed.Last()) >= new Cost(3))
break;
}
player.EndDrawing();
if (player.Revealed.Count > 0)
{
Card lastCard = player.Revealed.Last();
if (player._Game.Cost(player.Revealed.Last()) >= new Cost(3))
player.AddCardInto(DeckLocation.Hand, player.RetrieveCardFrom(DeckLocation.Revealed, lastCard));
}
player.DiscardRevealed();
}
}
public class Scavenger : Card
{
public Scavenger()
: base("Scavenger", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCoin | Group.Terminal | Group.CardOrdering)
{
this.BaseCost = new Cost(4);
this.Benefit.Currency.Coin.Value = 2;
this.Text = "You may put your deck into your discard pile. Look through your discard pile and put one card from it on top of your deck.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choice = Choice.CreateYesNoChoice("You may put your deck into your discard pile.", this, this, player, null);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options[0] == "Yes")
{
player._Game.SendMessage(player, this);
CardCollection cc = player.RetrieveCardsFrom(DeckLocation.Deck);
player.AddCardsInto(DeckLocation.Discard, cc);
}
CardCollection cards = player.DiscardPile.LookThrough(c => true);
Choice choiceTop = new Choice("Choose a card to put onto your deck", this, cards, player, false, 0, 1);
ChoiceResult resultTop = player.MakeChoice(choiceTop);
if (resultTop.Cards.Count > 0)
player.AddCardsToDeck(player.DiscardPile.Retrieve(player, c => resultTop.Cards.Contains(c)), DeckPosition.Top);
}
}
public class Shelters : Card
{
public Shelters()
: base("Shelters", Category.Shelter, Source.DarkAges, Location.Invisible, Group.None)
{
}
public override void Setup(Game game, Supply supply)
{
for (int i = 0; i < game.Players.Count; i++)
{
supply.AddTo(new Hovel());
supply.AddTo(new Necropolis());
supply.AddTo(new OvergrownEstate());
}
}
}
public class SirBailey : Knight
{
public SirBailey()
: base("Sir Bailey", Category.Action | Category.Attack | Category.Knight, Group.PlusCard | Group.PlusAction | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class SirDestry : Knight
{
public SirDestry()
: base("Sir Destry", Category.Action | Category.Attack | Category.Knight, Group.PlusCard | Group.Terminal | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Benefit.Cards = 2;
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class SirMartin : Knight
{
public SirMartin()
: base("Sir Martin", Category.Action | Category.Attack | Category.Knight, Group.PlusBuy | Group.Terminal | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(4);
this.Benefit.Buys = 2;
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class SirMichael : Knight
{
public SirMichael()
: base("Sir Michael", Category.Action | Category.Attack | Category.Knight, Group.Terminal | Group.Trash | Group.Discard)
{
this.BaseCost = new Cost(5);
this.Text = "Each other player discards down to 3 cards in hand.Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.";
}
public override Type BaseType { get { return TypeClass.Knights; } }
public override void Play(Player player)
{
base.Play(player);
IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player);
enumerator.MoveNext();
while (enumerator.MoveNext())
{
Player attackee = enumerator.Current;
if (this.IsAttackBlocked[attackee])
continue;
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);
}
this.KnightAttack(player);
}
}
public class SirVander : Knight
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public SirVander()
: base("Sir Vander", Category.Action | Category.Attack | Category.Knight, Group.Terminal | Group.Trash | Group.Discard | Group.ReactToTrashing | Group.Gain)
{
this.BaseCost = new Cost(5);
this.Text = "Each other player reveals the top 2 cards of his deck, trashes one of them costing from 3 to 6, and discards the rest. If a Knight is trashed by this, trash this card.
When you trash this, gain a Gold.";
this.OwnerChanged += new OwnerChangedEventHandler(SirVander_OwnerChanged);
}
public override Type BaseType { get { return TypeClass.Knights; } }
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(SirVander_OwnerChanged);
}
void SirVander_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.SirVander) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.SirVander] = new TrashAction(this.Owner, this, "Gain a Gold", player_GainGold, true);
}
internal void player_GainGold(Player player, ref TrashEventArgs e)
{
player.Gain(player._Game.Table.Gold);
e.HandledBy.Add(this);
}
public override void Play(Player player)
{
base.Play(player);
this.KnightAttack(player);
}
}
public class Spoils : Card
{
public const int BaseCount = 15;
public Spoils()
: base("Spoils", Category.Treasure, Source.DarkAges, Location.Special, Group.DeckReduction | Group.PlusCoin)
{
this.BaseCost = new Cost(0, true);
this.Benefit.Currency = new Currency(3);
this.Text = "When you play this, return it to the Spoils pile.(This is not in the Supply.)";
}
public override void Play(Player player)
{
base.Play(player);
if (player.Tableau.Contains(this))
{
Card cardToReturn = player.RetrieveCardFrom(DeckLocation.Tableau, this);
Supply supply = player._Game.Table.SpecialPiles[TypeClass.Spoils];
player.Lose(this);
supply.AddTo(this);
player._Game.SendMessage(player, this, supply, 1);
}
}
}
public class Squire : Card
{
private Player.TrashedEventHandler _TrashedEventHandler = null;
public Squire()
: base("Squire", Category.Action, Source.DarkAges, Location.Kingdom, Group.Gain | Group.PlusAction | Group.PlusBuy | Group.PlusCoin | Group.PlusMultipleActions | Group.ReactToTrashing)
{
this.BaseCost = new Cost(2);
this.Benefit.Currency = new Currency(1);
this.Text = "Choose one: +2Actions; or +2Buys; or gain a Silver.
When you trash this,gain an Attack card.";
this.OwnerChanged += new OwnerChangedEventHandler(Squire_OwnerChanged);
}
internal override void TearDown()
{
base.TearDown();
this.OwnerChanged -= new OwnerChangedEventHandler(Squire_OwnerChanged);
}
void Squire_OwnerChanged(object sender, OwnerChangedEventArgs e)
{
if (_TrashedEventHandler != null && e.OldOwner != null)
{
e.OldOwner.Trashed -= _TrashedEventHandler;
_TrashedEventHandler = null;
}
if (e.NewOwner != null)
{
_TrashedEventHandler = new Player.TrashedEventHandler(player_Trashed);
e.NewOwner.Trashed += _TrashedEventHandler;
}
}
void player_Trashed(object sender, TrashEventArgs e)
{
Player player = sender as Player;
// Already being processed or been handled -- don't need to process this one
if (e.Actions.ContainsKey(TypeClass.Squire) || e.HandledBy.Contains(this))
return;
if (e.TrashedCards.Contains(this))
e.Actions[TypeClass.Squire] = new TrashAction(this.Owner, this, "Gain an Attack card", player_GainAttack, true);
}
internal void player_GainAttack(Player player, ref TrashEventArgs e)
{
SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(
supply => supply.CanGain() &&
((supply.Category & Cards.Category.Attack) == Cards.Category.Attack));
Choice choice = new Choice("Gain an Attack card", this, gainableSupplies, player, true);
ChoiceResult result = player.MakeChoice(choice);
if (result.Supply != null)
player.Gain(result.Supply);
e.HandledBy.Add(this);
}
public override void Play(Player player)
{
base.Play(player);
CardBenefit benefit = new CardBenefit();
Choice choice = new Choice("Choose one:", this, new CardCollection() { this }, new List() { "+2Actions", "+2Buys", "Gain a Silver" }, player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options.Contains("+2Actions"))
benefit.Actions = 2;
else if (result.Options.Contains("+2Buys"))
benefit.Buys = 2;
else
player.Gain(player._Game.Table.Silver);
player.ReceiveBenefit(this, benefit);
}
}
public class Storeroom : Card
{
public Storeroom()
: base("Storeroom", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusBuy | Group.Terminal | Group.Discard | Group.PlusCard | Group.PlusCoin)
{
this.BaseCost = new Cost(3);
this.Benefit.Buys = 1;
this.Text = "Discard any number of cards.+1 Card per card discarded.Discard any number of cards.+1 per card discarded the second time.";
}
public override void Play(Player player)
{
base.Play(player);
Choice choiceDiscardTheFirst = new Choice("Discard any number of cards. +1 Card per card discarded", this, player.Hand, player, false, 0, player.Hand.Count);
ChoiceResult resultDiscardTheFirst = player.MakeChoice(choiceDiscardTheFirst);
player.Discard(DeckLocation.Hand, resultDiscardTheFirst.Cards);
player.ReceiveBenefit(this, new CardBenefit() { Cards = resultDiscardTheFirst.Cards.Count });
Choice choiceDiscardTheSecond = new Choice("Discard any number of cards. +1 per card discarded.", this, player.Hand, player, false, 0, player.Hand.Count);
ChoiceResult resultDiscardTheSecond = player.MakeChoice(choiceDiscardTheSecond);
player.Discard(DeckLocation.Hand, resultDiscardTheSecond.Cards);
player.ReceiveBenefit(this, new CardBenefit() { Currency = new Currency(resultDiscardTheSecond.Cards.Count) });
}
}
public class Survivors : Card
{
public Survivors()
: base("Survivors", Category.Action | Category.Ruins, Source.DarkAges, Location.General, Group.CardOrdering | Group.Discard | Group.Terminal)
{
this.BaseCost = new Cost(0);
this.Text = "Look at the top 2 cards of your deck. Discard them or put them back in any order.";
}
public override Type BaseType { get { return TypeClass.RuinsSupply; } }
public override void Play(Player player)
{
base.Play(player);
CardCollection newCards = player.Draw(2, DeckLocation.Private);
Choice choice = new Choice(
String.Format("Do you want to discard {0} or put them back on top?", String.Join(" and ", newCards.Select(c => c.Name))),
this,
newCards,
new List() { "Discard", "Put them back" },
player);
ChoiceResult result = player.MakeChoice(choice);
if (result.Options[0] == "Discard")
player.Discard(DeckLocation.Private);
else
{
Choice replaceChoice = new Choice("Choose order of cards to put back on your deck", this, player.Private, player, true, 2, 2);
ChoiceResult replaceResult = player.MakeChoice(replaceChoice);
player.RetrieveCardsFrom(DeckLocation.Private);
player.AddCardsToDeck(replaceResult.Cards, DeckPosition.Top);
}
}
}
public class Urchin : Card
{
private Player.CardPlayedEventHandler _CardPlayedEventHandler = null;
public Urchin()
: base("Urchin", Category.Action | Category.Attack, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.Discard | Group.Trash | Group.Gain)
{
this.BaseCost = new Cost(3);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Text = "Each other player discards down to 4 cards in hand.
When you play another Attack card with this in play, you may trash this. If you do, gain a Mercenary from the Mercenary pile.";
}
public override void Setup(Game game, Supply supply)
{
base.Setup(game, supply);
if (!game.Table.SpecialPiles.ContainsKey(TypeClass.Mercenary))
{
Supply mercenarySupply = new Supply(game, game.Players, TypeClass.Mercenary, Mercenary.BaseCount);
mercenarySupply.Setup();
game.Table.SpecialPiles.Add(TypeClass.Mercenary, mercenarySupply);
}
}
public override void Play(Player player)
{
base.Play(player);
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;
Choice choice = new Choice("Choose cards to discard. You must discard down to 4 cards in hand", this, attackee.Hand, attackee, false, attackee.Hand.Count - 4, attackee.Hand.Count - 4);
ChoiceResult result = attackee.MakeChoice(choice);
attackee.Discard(DeckLocation.Hand, result.Cards);
}
_CardPlayedEventHandler = new Player.CardPlayedEventHandler(ActivePlayer_CardPlayed);
player.CardPlayed += _CardPlayedEventHandler;
}
void ActivePlayer_CardPlayed(object sender, CardPlayedEventArgs e)
{
if (e.Cards.Count(c => c != this && (c.Category & Cards.Category.Attack) == Cards.Category.Attack) > 0)
{
Choice choicePlayer = Choice.CreateYesNoChoice("Do you want to trash Urchin?", this, e.Player);
ChoiceResult resultPlayer = e.Player.MakeChoice(choicePlayer);
if (resultPlayer.Options[0] == "Yes")
{
if (e.Player.Tableau.Contains(this))
e.Player.Trash(e.Player.RetrieveCardFrom(DeckLocation.Tableau, this));
else if (e.Player.PreviousTableau.Contains(this))
e.Player.Trash(e.Player.RetrieveCardFrom(DeckLocation.PreviousTableau, this));
else
return;
e.Player.Gain(e.Player._Game.Table.SpecialPiles[TypeClass.Mercenary]);
}
}
}
public override void RemovedFrom(DeckLocation location, Player player)
{
base.RemovedFrom(location, player);
if (_CardPlayedEventHandler != null)
player.CardPlayed -= _CardPlayedEventHandler;
_CardPlayedEventHandler = null;
}
}
public class Vagrant : Card
{
public Vagrant()
: base("Vagrant", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.CardOrdering)
{
this.BaseCost = new Cost(2);
this.Benefit.Cards = 1;
this.Benefit.Actions = 1;
this.Text = "Reveal the top card of your deck. If it's a Curse, Ruins, Shelter, or Victory card, put it into your hand.";
}
public override void Play(Player player)
{
base.Play(player);
CardCollection newCards = player.Draw(1, DeckLocation.Revealed);
player.AddCardsToHand(player.RetrieveCardsFrom(DeckLocation.Revealed,
c => (c.Category & Cards.Category.Curse) == Cards.Category.Curse ||
(c.Category & Cards.Category.Ruins) == Cards.Category.Ruins ||
(c.Category & Cards.Category.Shelter) == Cards.Category.Shelter ||
(c.Category & Cards.Category.Victory) == Cards.Category.Victory
));
player.AddCardsToDeck(player.RetrieveCardsFrom(DeckLocation.Revealed), DeckPosition.Top);
}
}
public class WanderingMinstrel : Card
{
public WanderingMinstrel()
: base("Wandering Minstrel", Category.Action, Source.DarkAges, Location.Kingdom, Group.PlusCard | Group.PlusAction | Group.PlusMultipleActions | Group.CardOrdering | Group.Discard)
{
this.BaseCost = new Cost(4);
this.Benefit.Cards = 1;
this.Benefit.Actions = 2;
this.Text = "Reveal the top 3 cards of your deck. Put the Actions back on top in any order and discard the rest.";
}
public override void Play(Player player)
{
base.Play(player);
player.Draw(3, DeckLocation.Revealed);
CardCollection actionCards = player.Revealed[Cards.Category.Action];
Choice replaceChoice = new Choice("Choose order of cards to put back on your deck", this, actionCards, player, true, actionCards.Count, actionCards.Count);
ChoiceResult replaceResult = player.MakeChoice(replaceChoice);
player.AddCardsToDeck(player.RetrieveCardsFrom(DeckLocation.Revealed, replaceResult.Cards), DeckPosition.Top);
player.DiscardRevealed();
}
}
}