internal void Trash(DeckLocation location, CardCollection cards)
		{
			if (cards.Count == 0)
				return;

			TrashEventArgs tea = null;

			if (Trashing != null)
			{
				do
				{
					tea = new TrashEventArgs(this, cards);
					Trashing(this, tea);

					Boolean isAnyRequired = false;
					List<String> options = new List<String>();
					IEnumerable<Type> cardTypes = tea.Actions.Keys;
					foreach (Type key in cardTypes)
					{
						options.Add(tea.Actions[key].Text);
						isAnyRequired |= tea.Actions[key].IsRequired;
					}

					if (options.Count > 0)
					{
						options.Sort();
						Choice choice = new Choice(String.Format("You are trashing {0} cards", cards.Count), null, cards, options, this, tea, false, isAnyRequired ? 1 : 0, 1);
						ChoiceResult result = this.MakeChoice(choice);

						if (result.Options.Count > 0)
							tea.Actions.First(kvp => kvp.Value.Text == result.Options[0]).Value.Method(this, ref tea);
					}
				} while (Trashing != null && tea.HandledBy.Count > 0);
			}

			this.MoveToTrashStart(location, cards);
			if (CurrentTurn != null)
				CurrentTurn.Trashed(cards);

			if (Trashed != null)
			{
				List<Object> handledBy = new List<Object>();
				Boolean actionPerformed = false;
				do
				{
					actionPerformed = false;

					tea = new TrashEventArgs(this, cards);
					tea.HandledBy.AddRange(handledBy);
					Trashed(this, tea);
					handledBy = tea.HandledBy;

					IEnumerator<Player> enumerator = this._Game.GetPlayersStartingWithEnumerator(this);
					while (enumerator.MoveNext())
					{
						Boolean isAnyRequired = false;
						List<String> options = new List<String>();
						IEnumerable<Type> cardTypes = tea.Actions.Keys;
						foreach (Type key in cardTypes)
						{
							if (enumerator.Current == tea.Actions[key].Player)
							{
								options.Add(tea.Actions[key].Text);
								isAnyRequired |= tea.Actions[key].IsRequired;
							}
						}
						if (options.Count > 0)
						{
							options.Sort();
							Choice choice = new Choice(String.Format("{0} trashed {1}", this == enumerator.Current ? "You" : this.ToString(), Utilities.StringUtility.Plural("card", cards.Count)), null, cards, options, this, tea, false, isAnyRequired ? 1 : 0, 1);
							ChoiceResult result = enumerator.Current.MakeChoice(choice);

							if (result.Options.Count > 0)
							{
								tea.Actions.First(kvp => kvp.Value.Text == result.Options[0]).Value.Method(enumerator.Current, ref tea);
								actionPerformed = true;
							}
						}
					}
				} while (Trashed != null && actionPerformed);
			}

			cards.TrashedBy(this);
			Lose(cards);

			if (TrashedFinished != null)
			{
				tea = new TrashEventArgs(this, cards);
				TrashedFinished(this, tea);
			}

			cards.RemovedFrom(location, this);
		}
		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.PhysicalCard))
				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);
		}
		internal void player_PlusCard(Player player, ref TrashEventArgs e)
		{
			SupplyCollection gainableSupplies = player._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost < player._Game.ComputeCost(this));
			Choice choice = new Choice(String.Format("Gain a card costing less than {0}", player._Game.ComputeCost(this).ToString()), this, gainableSupplies, player, false);
			ChoiceResult result = player.MakeChoice(choice);
			if (result.Supply != null)
				player.Gain(result.Supply);

			e.HandledBy.Add(this);
		}
		internal void player_PlusCard(Player player, ref TrashEventArgs e)
		{
			player.ReceiveBenefit(this, new CardBenefit() { Cards = 3 });

			e.HandledBy.Add(this);
		}
		internal void player_GainGold(Player player, ref TrashEventArgs e)
		{
			player.Gain(player._Game.Table.Gold);

			e.HandledBy.Add(this);
		}
		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, false);
			ChoiceResult result = player.MakeChoice(choice);
			if (result.Supply != null)
				player.Gain(result.Supply);

			e.HandledBy.Add(this);
		}
		internal void player_DiscardMarketSquare(Player player, ref TrashEventArgs e)
		{
			player.Discard(DeckLocation.Hand, this);
			player.Gain(player._Game.Table.Gold);

			e.HandledBy.Add(this);
		}
		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.PhysicalCard))
				e.Actions[TypeClass.OvergrownEstate] = new TrashAction(this.Owner, this, "+1 Card", player_PlusCard, true);
		}
		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_PlusCard(Player player, ref TrashEventArgs e)
		{
			Choice choice = new Choice("Choose one:", this, new CardCollection() { this }, new List<string>() { "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);
		}
		internal void player_RegainFortress(Player player, ref TrashEventArgs e)
		{
			if (player._Game.Table.Trash.Contains(this.PhysicalCard))
			{
				player.Gain(player._Game.Table.Trash, this.PhysicalCard, DeckLocation.Hand, DeckPosition.Automatic);
				_TrashedFinishedEventHandler = new Player.TrashedFinishedEventHandler(player_TrashedFinished);
				player.TrashedFinished += _TrashedFinishedEventHandler;
			}

			e.HandledBy.Add(this);
		}
		void player_TrashedFinished(object sender, TrashEventArgs e)
		{
			this.PhysicalCard.ObtainedBy(e.CurrentPlayer);
			if (_TrashedFinishedEventHandler != null)
				e.CurrentPlayer.TrashedFinished -= _TrashedFinishedEventHandler;
			_TrashedFinishedEventHandler = 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.Fortress) || e.HandledBy.Contains(this))
				return;

			if (e.TrashedCards.Contains(this.PhysicalCard))
				e.Actions[TypeClass.Fortress] = new TrashAction(this.Owner, this, "Put Fortress into your hand", player_RegainFortress, true);
		}