using DominionBase.Currencies; using DominionBase.Enums; using DominionBase.Piles; using DominionBase.Players; using DominionBase.Properties; using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; namespace DominionBase.Cards.DarkAges2019Errata { public static class TypeClass { //public static readonly Type BandOfMisfits = typeof(BandOfMisfits); //public static readonly Type DeathCart = typeof(DeathCart); //public static readonly Type Pillage = typeof(Pillage); //public static readonly Type Procession = typeof(Procession); } public class BandOfMisfits : Card { private List PlayedCards = new List(); public BandOfMisfits() : this(Edition.Errata2019) { } public BandOfMisfits(Edition edition) : base(Categories.Action | Categories.Command, Source.DarkAges, Location.Kingdom, Traits.ConditionalBenefit, edition: edition) { BaseCost = new Cost(5); } public override bool CanCleanUp { get => PlayedCards.All(cp => cp.CanCleanUp) && base.CanCleanUp; } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); var availableCards = new SupplyCollection(player._Game.Table.TableEntities.FindAll( supply => supply.Any() && supply.TopCard.Category.HasFlag(Categories.Action) && !supply.TopCard.Category.HasFlag(Categories.Command) && supply.CurrentCost < player._Game.ComputeCost(this) )); var choice = new Choice(Resource.PlayNonCommandAction, this, availableCards, ChoiceOutcome.Select, player, false); var result = player.MakeChoice(choice); if (result.Cards.Any()) { var card = result.Cards[0]; PlayedCards.Add(card); card.ModifiedBy = this; player.Actions++; var previousPlayerMode = player.PutCardIntoPlay(card); var logicalCard = card.LogicalCard; player.PlayCard(logicalCard, previousPlayerMode); } else player.PlayNothing(); } } public class DeathCart : DarkAges.Looter { public DeathCart() : this(Edition.Errata2019) { } public DeathCart(Edition edition) : base(Categories.Action, Traits.PlusCoin | Traits.Trasher | Traits.Gainer | Traits.Terminal, edition) { BaseCost = new Cost(4); } public override void SetupCard(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.SetupCard(game); foreach (var player in game.Players) player.CardGained += Player_CardGained; } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.TearDown(game); foreach (var player in game.Players) player.CardGained -= Player_CardGained; } private void Player_CardGained(object sender, Players.CardGainEventArgs e) { var player = sender as IPlayer; var key = Type.ToString(); // This is not the card you are looking for if (e.Card != this || e.Resolvers.ContainsKey(key) || e.HandledBy.Contains(this) || !((ISupply)e.Game.Table[DarkAges.TypeClass.RuinsSupply]).CanGain()) return; e.Resolvers[key] = new CardGainResolver(player, this, "GainRuins", Resource.Gain2Ruins, Player_GainDeathCart, true); } internal void Player_GainDeathCart(IPlayer player, ref Players.CardGainEventArgs e) { player.Gain((ISupply)player._Game.Table[DarkAges.TypeClass.RuinsSupply], this, 2); e.HandledBy.Add(this); } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); var choiceTrash = new Choice("You may trash an Action card (otherwise, trash this)", this, player.Hand[Categories.Action], ChoiceOutcome.Trash, player, minimum: 0); var resultTrash = player.MakeChoice(choiceTrash); Card toTrash = null; if (resultTrash.Cards.Any()) toTrash = player.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards).FirstOrDefault(); else if (player.InPlay.Contains(PhysicalCard)) toTrash = player.RetrieveCardFrom(DeckLocation.InPlay, PhysicalCard); if (toTrash != null) { player.Trash(this, toTrash); player.ReceiveBenefit(this, new CardBenefit { Currency = new Currency(5) }); } } } public class Pillage : Card { public Pillage() : this(Edition.Errata2019) { } public Pillage(Edition edition) : base(Categories.Action | Categories.Attack, Source.DarkAges, Location.Kingdom, Traits.Discard | Traits.Gainer | Traits.IncludesExtraPiles | Traits.Terminal | Traits.Trasher, edition: edition) { BaseCost = new Cost(5); } public override void SetupSupply(IGame game, ISupply supply) { Contract.Requires(game != null, "game cannot be null"); base.SetupSupply(game, supply); DarkAges.Spoils.SetupSupply(game); } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); Card toTrash = null; if (player.InPlay.Contains(PhysicalCard)) toTrash = player.RetrieveCardFrom(DeckLocation.InPlay, PhysicalCard); if (toTrash != null) { player.Trash(this, toTrash); var enumerator = player._Game.GetPlayersStartingWithEnumerator(player); enumerator.MoveNext(); while (enumerator.MoveNext()) { var attackee = enumerator.Current; // Skip if the attack is blocked (Moat, Lighthouse, etc.) if (IsAttackBlocked[attackee]) continue; if (attackee.Hand.Count < 5) continue; attackee.RevealHand(); var choice = new Choice($"Choose a card for {attackee} to discard.", this, attackee.Revealed, ChoiceOutcome.Discard, attackee); var result = player.MakeChoice(choice); attackee.Discard(DeckLocation.Revealed, result.Cards); attackee.ReturnHand(attackee.Revealed[c => true]); } player.Gain((ISupply)player._Game.Table.SpecialPiles[DarkAges.TypeClass.Spoils], this, 2); } } } public class Procession : Card { private readonly List CardsPlayed = new List(); public Procession() : this(Edition.Errata2019) { } public Procession(Edition edition) : base(Categories.Action, Source.DarkAges, Location.Kingdom, Traits.Trasher | Traits.Gainer | Traits.Multiplier, edition: edition) { BaseCost = new Cost(4); } public override bool CanCleanUp { get => CardsPlayed.All(cp => cp.CanCleanUp) && base.CanCleanUp; } public override void AddedTo(DeckLocation location, IPlayer player) { base.AddedTo(location, player); CardsPlayed.Clear(); } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); var choice = new Choice( Resource.ChooseActionPlay2x, this, player.Hand[c => c.Category.HasFlag(Categories.Action) && !c.Category.HasFlag(Categories.Duration)], ChoiceOutcome.Select, player, minimum: 0 ); var result = player.MakeChoice(choice); if (result.Cards.Any()) { var cardToPlayTwice = result.Cards[0]; CardsPlayed.Add(cardToPlayTwice); cardToPlayTwice.ModifiedBy = this; player.Actions++; var previousPlayerMode = player.PutCardIntoPlay(cardToPlayTwice); var logicalCard = cardToPlayTwice.LogicalCard; player.PlayCard(cardToPlayTwice.LogicalCard, previousPlayerMode); player.Actions++; previousPlayerMode = player.PutCardIntoPlay(cardToPlayTwice, Resource.AgainFromCard.Replace("{card}", this.ToString())); player.PlayCard(logicalCard, previousPlayerMode); if (player.InPlay.Contains(cardToPlayTwice.PhysicalCard)) player.Trash(this, DeckLocation.InPlay, cardToPlayTwice.PhysicalCard); var trashedCardCost = player._Game.ComputeCost(cardToPlayTwice); var gainableSupplies = new SupplyCollection(player._Game.Table.TableEntities.FindAll( supply => supply.CanGain() && supply.TopCard.Category.HasFlag(Categories.Action) && supply.CurrentCost == (trashedCardCost + new Coin(1)) )); var choiceGain = new Choice(Resource.GainAction, this, gainableSupplies, ChoiceOutcome.Gain, player, false); var resultGain = player.MakeChoice(choiceGain); if (resultGain.Supply != null) player.Gain(resultGain.Supply, this); } else player.PlayNothing(); } protected override void ModifyDuration(IPlayer player, Card card) { base.ModifyDuration(player, card); base.ModifyDuration(player, card); } } }