using DominionBase.Currencies; using DominionBase.Enums; using DominionBase.Piles; using DominionBase.Players; using DominionBase.Properties; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; namespace DominionBase.Cards.Renaissance { public class Improve : Card { private List _CleaningUpEventHandlers = new List(); public Improve() : base(Categories.Action, Source.Renaissance, Location.Kingdom, Traits.DeckReduction | Traits.Gainer | Traits.PlusCoin | Traits.ReactToDiscard | Traits.Terminal | Traits.Trasher) { BaseCost = new Cost(3); Benefit.Currency.Coin.Value = 2; } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.TearDown(game); foreach (var player in game.Players) { foreach (var eh in _CleaningUpEventHandlers) player.CleaningUp -= eh; player.CleanedUp -= Player_CleanedUp; } _CleaningUpEventHandlers.Clear(); } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); if (!_CleaningUpEventHandlers.Any()) player.CleanedUp += Player_CleanedUp; var handler = new CleaningUpEventHandler(Player_CleaningUp); player.CleaningUp += handler; _CleaningUpEventHandlers.Add(handler); } private void Player_CleaningUp(object sender, CleaningUpEventArgs e) { if (e.Resolvers.ContainsKey(Type)) return; var canTrash = e.CardsMovements.Where(cm => cm.Card.Category.HasFlag(Categories.Action) && cm.Destination == DeckLocation.Discard); if (!canTrash.Any()) return; e.Resolvers[Type] = new CleaningUpResolver(this, $"Trash an Action card in play", Player_Action); } internal void Player_Action(IPlayer player, ref CleaningUpEventArgs e) { var canTrash = e.CardsMovements .Where(cm => cm.Card.Category.HasFlag(Categories.Action) && cm.Destination == DeckLocation.Discard) .Select(cm => cm.Card); var choiceTrash = new Choice(Resource.ChooseACardToTrash, this, canTrash, ChoiceOutcome.Trash, player, minimum: 0); var resultTrash = player.MakeChoice(choiceTrash); if (resultTrash.Cards.Any()) { var toTrash = resultTrash.Cards[0]; var movement = e.CardsMovements.Find(cm => cm.Card == toTrash); var trashedCardCost = player._Game.ComputeCost(toTrash); player.Trash(this, movement.CurrentLocation, movement.Card); e.CardsMovements.Remove(movement); var gainableSupplies = new SupplyCollection( player._Game.Table.TableEntities.FindAll(supply => supply.CanGain() && supply.CurrentCost == (trashedCardCost + new Coin(1))) ); var choice = new Choice(Resource.GainCard, this, gainableSupplies, ChoiceOutcome.Gain, player, false); var result = player.MakeChoice(choice); if (result.Supply != null) player.Gain(result.Supply, this); } player.CleaningUp -= _CleaningUpEventHandlers[0]; _CleaningUpEventHandlers.RemoveAt(0); } private void Player_CleanedUp(object sender, CleanedUpEventArgs e) { var player = sender as IPlayer; foreach (var eh in _CleaningUpEventHandlers) player.CleaningUp -= eh; _CleaningUpEventHandlers.Clear(); player.CleanedUp -= Player_CleanedUp; } } }