using DominionBase.Enums; using DominionBase.Players; using DominionBase.Properties; using System.Diagnostics.Contracts; using System.Linq; namespace DominionBase.Cards.Renaissance { public class Research : Card { private readonly CardCollection _setAsideCards = new CardCollection(); public Research() : base(Categories.Action | Categories.Duration, Source.Renaissance, Location.Kingdom, Traits.ConditionalBenefit | Traits.DeckReduction | Traits.PlusAction | Traits.RemoveCurses | Traits.RemoveFromHand | Traits.Trasher | Traits.TrashForBenefit) { BaseCost = new Cost(4); Benefit.Actions = 1; } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.TearDown(game); _setAsideCards.Clear(); foreach (var player in game.Players) { player.TurnEnded -= Player_TurnEnded; player.TurnStarted -= Player_TurnStarted; } } public override bool IsStackable => _setAsideCards.Count == 0; public override DisplayableCollection Stack() { var cc = new DisplayableCollection(); _setAsideCards.ForEach(c => cc.Add(Universal.Utility.GenerateCardBack(c.CardBack))); cc.Add(this); return cc; } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); var choice = new Choice(Resource.ChooseACardToTrash, this, player.Hand, ChoiceOutcome.Trash, player); var result = player.MakeChoice(choice); if (result.Cards.Any()) { player.Trash(this, player.RetrieveCardFrom(DeckLocation.Hand, result.Cards[0])); var cardCost = player._Game.ComputeCost(result.Cards[0]); var toSetAside = cardCost.Coin.Value; // This currently has an issue, as "Set aside" isn't the same as "draw from", // as it should skip the -1 card token from Adventures player.Draw(toSetAside, DeckLocation.Private); var cardsToSetAside = player.RetrieveCardsFrom(DeckLocation.Private); if (cardsToSetAside.Any()) { _setAsideCards.AddRange(cardsToSetAside); player._Game.SendMessage(player, this, "SetAside", cardsToSetAside.ToArray()); CanCleanUpPlayed.Add(false); player.TurnEnded += Player_TurnEnded; } else CanCleanUpPlayed.Add(true); } } private void Player_TurnEnded(object sender, TurnEndedEventArgs e) { e.Player.TurnEnded -= Player_TurnEnded; e.Player.TurnStarted += Player_TurnStarted; } public override void ResolveDuration(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.ResolveDuration(player); if (_setAsideCards.Any()) { player.AddCardsToHand(_setAsideCards); _setAsideCards.Clear(); } } public override void PerformEndgameCalculations(IPlayer player, PointsCollection collection) { Contract.Requires(collection != null, "collection cannot be null"); // Add back any set aside cards that are still on this collection.AddRange(_setAsideCards); _setAsideCards.Clear(); } private void Player_TurnStarted(object sender, TurnStartedEventArgs e) { var key = ToString(); if (!e.Resolvers.ContainsKey(key)) e.Resolvers[key] = new TurnStartedResolver(e.Player, this, Resource.ResolveCard.Replace("{card}", PhysicalCard.ToString()), Player_Action, true); } internal void Player_Action(IPlayer player, ref TurnStartedEventArgs e) { ResolveDuration(e.Player); CanCleanUpPlayed.Remove(false); e.Player.TurnStarted -= Player_TurnStarted; } } }