using System; using System.Collections.Generic; using System.Linq; using System.Text; using DominionBase.Currencies; using DominionBase.Piles; using DominionBase.Players; namespace DominionBase.Cards.Promotional { public static class TypeClass { //public static Type BlackMarket = typeof(BlackMarket); public static Type Envoy = typeof(Envoy); public static Type Governor = typeof(Governor); public static Type Stash = typeof(Stash); public static Type WalledVillage = typeof(WalledVillage); public static Type BlackMarketSupply = typeof(BlackMarketSupply); } public class BlackMarket : Card { public BlackMarket() : base("Black Market", Category.Action, Source.Promotional, Location.Kingdom, Group.PlusCoin | Group.PlusBuy | Group.Terminal) { this.BaseCost = new Cost(4); this.Benefit.Currency.Coin.Value = 2; this.Text = "Reveal the top 3 cards of the Black Market deck. You may buy one of them immediately.Put the unbought cards on the bottom of the Black Market deck in any order.
(Before the game, make a Black Market deck out of one copy of each Kingdom card not in the supply.)"; } public override void Play(Player player) { base.Play(player); player.Draw(5, DeckLocation.Revealed); } public override void Setup(Game game, Supply supply) { base.Setup(game, supply); Supply blackMarketSupply = new Supply(game, game.Players, TypeClass.BlackMarketSupply, Visibility.All); blackMarketSupply.Setup(); game.Table.SpecialPiles.Add(TypeClass.BlackMarketSupply, blackMarketSupply); } public override void CheckSetup(Preset preset, Table table) { preset.CardCards[this] = new CardCollection(); // Grab all of the Black Market Supply cards and stick them into the CardCards for Black Market foreach (Type cardType in table.SpecialPiles[TypeClass.BlackMarketSupply].CardTypes) preset.CardCards[this].Add(Card.CreateInstance(cardType)); } public override List GetSerializingTypes() { return new List() { typeof(BlackMarket_NumberOfCards), typeof(BlackMarket_UseGameConstraints), typeof(BlackMarket_Constraints) }; //, typeof(BlackMarket_ErrorOnNotEnoughCards) }; } public override CardSettingCollection GenerateSettings() { CardSettingCollection csc = new CardSettingCollection(); csc.Add(new BlackMarket_NumberOfCards { Value = 25 }); csc.Add(new BlackMarket_UseGameConstraints { Value = false }); csc.Add(new BlackMarket_Constraints { Value = new ConstraintCollection() }); //csc.Add(new BlackMarket_ErrorOnNotEnoughCards { Value = true }); return csc; } public override void FinalizeSettings(CardSettingCollection settings) { (settings[typeof(BlackMarket_Constraints)].Value as ConstraintCollection).MaxCount = 100; } [Serializable] public class BlackMarket_NumberOfCards : CardSetting { public override String Name { get { return "NumberOfCards"; } } public override String Text { get { return "Number of cards to use"; } } public override String Hint { get { return "Number of cards to use in the Black Market supply pile"; } } public override Type Type { get { return typeof(int); } } public override int DisplayOrder { get { return 0; } } public override Object LowerBounds { get { return 1; } } public override Boolean UseLowerBounds { get { return true; } } public override Boolean IsLowerBoundsInclusive { get { return true; } } } [Serializable] public class BlackMarket_UseGameConstraints : CardSetting { public override String Name { get { return "UseGameConstraints"; } } public override String Text { get { return "Use Game constraints instead of the ones listed below"; } } public override String Hint { get { return "Use the defined Game constraints instead of the ones defined here"; } } public override Type Type { get { return typeof(Boolean); } } public override int DisplayOrder { get { return 2; } } } [Serializable] public class BlackMarket_Constraints : CardSetting { public override String Name { get { return "Constraints"; } } public override String Hint { get { return "Constraints to use for selecting cards to use in the Black Market supply"; } } public override Type Type { get { return typeof(ConstraintCollection); } } public override int DisplayOrder { get { return 3; } } } //[Serializable] //public class BlackMarket_ErrorOnNotEnoughCards : CardSetting //{ // public override String Name { get { return "ErrorOnNotEnoughCards"; } } // public override String Text { get { return "Error when not enough matching, allowed cards are found"; } } // public override String Hint { get { return "Error when the game can't find enough cards to use for the Black Market supply pile"; } } // public override Type Type { get { return typeof(Boolean); } } // public override int DisplayOrder { get { return 1; } } //} } public class BlackMarketSupply : Card { public BlackMarketSupply() : base("Black Market Supply", Category.Unknown, Source.Promotional, Location.Invisible, Group.None) { } public override void Setup(Game game, Supply supply) { base.Setup(game, supply); IList availableCards = null; try { if (game.Settings.Preset != null) { availableCards = game.Settings.Preset.CardCards[game.Settings.Preset.Cards.First(c => c.CardType == typeof(BlackMarket))]; // Shuffle the preset cards -- these should definitely not be set up in a known order Utilities.Shuffler.Shuffle(availableCards); } else { int cardsToUse = 25; //Boolean errorOnNotEnoughCards = true; Boolean shouldUseGameConstraints = true; ConstraintCollection bmConstraints = new ConstraintCollection(); if (game.Settings.CardSettings.ContainsKey("Black Market")) { CardsSettings bmSettings = game.Settings.CardSettings["Black Market"]; cardsToUse = (int)bmSettings.CardSettingCollection[typeof(BlackMarket.BlackMarket_NumberOfCards)].Value; //errorOnNotEnoughCards = (Boolean)bmSettings.CardSettingCollection[typeof(BlackMarket.BlackMarket_ErrorOnNotEnoughCards)].Value; shouldUseGameConstraints = (Boolean)bmSettings.CardSettingCollection[typeof(BlackMarket.BlackMarket_UseGameConstraints)].Value; bmConstraints = (ConstraintCollection)bmSettings.CardSettingCollection[typeof(BlackMarket.BlackMarket_Constraints)].Value; } // need to set up a supply pile for Black Market; randomly pick an unused supply card and add it to the pile until we have the requisite number of cards availableCards = game.CardsAvailable; if (shouldUseGameConstraints) { // Skip all "Must Use" constraints ConstraintCollection constraints = new ConstraintCollection(game.Settings.Constraints.Where(c => c.ConstraintType != ConstraintType.CardMustUse)); availableCards = constraints.SelectCards(availableCards, cardsToUse); } else availableCards = bmConstraints.SelectCards(availableCards, cardsToUse); } } catch (DominionBase.Cards.ConstraintException ce) { throw new BlackMarketConstraintException(String.Format("Problem setting up Black Market constraints: {0}", ce.Message)); } foreach (Card cardToUse in availableCards) { game.CardsAvailable.Remove(cardToUse); supply.AddTo(cardToUse); } } } public class BlackMarketConstraintException : ConstraintException { public BlackMarketConstraintException() { } public BlackMarketConstraintException(string message) : base(message) { } public BlackMarketConstraintException(string message, Exception innerException) : base(message, innerException) { } internal BlackMarketConstraintException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } public class Envoy : Card { public Envoy() : base("Envoy", Category.Action, Source.Promotional, Location.Kingdom, Group.PlusCard | Group.Terminal) { this.BaseCost = new Cost(4); this.Text = "Reveal the top 5 cards from your deck. The player to your left chooses one for you to discard. Draw the rest."; } public override void Play(Player player) { base.Play(player); player.Draw(5, DeckLocation.Revealed); IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player); enumerator.MoveNext(); // Gets us... which we don't care about here. enumerator.MoveNext(); // Get the player to our left Player leftPlayer = enumerator.Current; Choice choice = new Choice(String.Format("Choose a card of {0}'s to discard", player), this, player.Revealed, player); ChoiceResult result = leftPlayer.MakeChoice(choice); // Discard the chosen card if (result.Cards.Count > 0) player.Discard(DeckLocation.Revealed, result.Cards[0]); player.AddCardsToHand(DeckLocation.Revealed); } } public class Governor : Card { public Governor() : base("Governor", Category.Action, Source.Promotional, Location.Kingdom, Group.PlusAction | Group.PlusCard | Group.AffectOthers | Group.DeckReduction | Group.Gain | Group.RemoveCurses | Group.Trash) { this.BaseCost = new Cost(5); this.Benefit.Actions = 1; this.Text = "Choose one; you get the version in parenthesis: Each player gets +1 (+3) Cards; or each player gains a Silver (Gold); or each player may trash a card from his hand and gain a card costing exactly 1 (2) more."; } public override void Play(Player player) { base.Play(player); Choice choice = new Choice("Choose 1. You get the version in parenthesis; everyone else gets the other:", this, new CardCollection() { this }, new List() { "+1 (+3) Cards", "gain a Silver (Gold)", "you may trash a card from your hand and gain a card costing exactly 1 (2) more" }, player); ChoiceResult result = player.MakeChoice(choice); IEnumerator enumerator = player._Game.GetPlayersStartingWithEnumerator(player); while (enumerator.MoveNext()) { Player actee = enumerator.Current; if (result.Options.Contains("+1 (+3) Cards")) { // 3 or 1 cards, depending on who it is actee.ReceiveBenefit(this, new CardBenefit() { Cards = (actee == player ? 3 : 1) }); } else if (result.Options.Contains("gain a Silver (Gold)")) { if (actee == player) actee.Gain(player._Game.Table.Gold); else actee.Gain(player._Game.Table.Silver); } else { Choice choiceTrash = new Choice("You may choose a card to trash", this, actee.Hand, actee, false, 0, 1); ChoiceResult resultTrash = actee.MakeChoice(choiceTrash); actee.Trash(actee.RetrieveCardsFrom(DeckLocation.Hand, resultTrash.Cards)); if (resultTrash.Cards.Count > 0) { Cost trashedCardCost = actee._Game.Cost(resultTrash.Cards[0]); SupplyCollection gainableSupplies = actee._Game.Table.Supplies.FindAll(supply => supply.CanGain() && supply.CurrentCost == (trashedCardCost + new Coin(actee == player ? 2 : 1))); Choice choiceGain = new Choice("Gain a card", this, gainableSupplies, actee, false); ChoiceResult resultGain = actee.MakeChoice(choiceGain); if (resultGain.Supply != null) actee.Gain(resultGain.Supply); } } } } } public class Stash : Card { private Player.ShuffledEventHandler _ShuffledEventHandler = null; public Stash() : base("Stash", Category.Treasure, Source.Promotional, Location.Kingdom, Group.PlusCoin, CardBack.Red) { this.BaseCost = new Cost(5); this.Benefit.Currency.Coin.Value = 2; this.Text = "
When you shuffle, you may put this anywhere in your deck."; this.OwnerChanged += new OwnerChangedEventHandler(Stash_OwnerChanged); } internal override void TearDown() { base.TearDown(); this.OwnerChanged -= new OwnerChangedEventHandler(Stash_OwnerChanged); } void Stash_OwnerChanged(object sender, OwnerChangedEventArgs e) { if (_ShuffledEventHandler != null && e.OldOwner != null) { e.OldOwner.Shuffled -= _ShuffledEventHandler; _ShuffledEventHandler = null; } if (e.NewOwner != null) { _ShuffledEventHandler = new Player.ShuffledEventHandler(player_Shuffled); e.NewOwner.Shuffled += _ShuffledEventHandler; } } public override void AddedTo(DeckLocation location, Player player) { base.AddedTo(location, player); switch (location) { case DeckLocation.Deck: _ShuffledEventHandler = new Player.ShuffledEventHandler(player_Shuffled); player.Shuffled += _ShuffledEventHandler; break; } } void player_Shuffled(object sender, ShuffleEventArgs e) { // Only do this if we're the first one if (e.HandledBy.Contains(this.CardType)) return; CardCollection deck = e.Player.DrawPile.Retrieve(e.Player, c => true); Choice choiceShuffle = new Choice("Cards have been shuffled. You may rearrange them", this, deck, Visibility.None, e.Player, true, deck.Count, deck.Count); ChoiceResult resultShuffle = e.Player.MakeChoice(choiceShuffle); e.Player.DrawPile.AddRange(e.Player, resultShuffle.Cards); e.HandledBy.Add(this.CardType); } public override void RemovedFrom(DeckLocation location, Player player) { base.RemovedFrom(location, player); if (_ShuffledEventHandler != null) player.Shuffled -= _ShuffledEventHandler; _ShuffledEventHandler = null; } } public class WalledVillage : Card { private Player.PhaseChangingEventHandler _PhaseChangingEventHandler = null; private Player.CleaningUpEventHandler _CleaningUpEventHandler = null; private Boolean _CanPutOnDeck = false; public WalledVillage() : base("Walled Village", Category.Action, Source.Promotional, Location.Kingdom, Group.CardOrdering | Group.PlusCard | Group.PlusAction | Group.PlusMultipleActions) { this.BaseCost = new Cost(4); this.Benefit.Cards = 1; this.Benefit.Actions = 2; this.Text = "
At the start of Clean-up, if you have this and no more than one other Action card in play, you may put this on top of your deck."; } public override void AddedTo(DeckLocation location, Player player) { base.AddedTo(location, player); switch (location) { case DeckLocation.Tableau: _PhaseChangingEventHandler = new Player.PhaseChangingEventHandler(player_PhaseChanging); player.PhaseChanging += _PhaseChangingEventHandler; _CleaningUpEventHandler = new Player.CleaningUpEventHandler(player_CleaningUp); player.CleaningUp += _CleaningUpEventHandler; _CanPutOnDeck = false; break; } } void player_PhaseChanging(object sender, PhaseChangingEventArgs e) { switch (e.NewPhase) { case PhaseEnum.Cleanup: if (e.CurrentPlayer.Tableau.Count(c => (c.Category & Cards.Category.Action) == Cards.Category.Action) + e.CurrentPlayer.PreviousTableau.Count(c => (c.Category & Cards.Category.Action) == Cards.Category.Action) <= 2) _CanPutOnDeck = true; else _CanPutOnDeck = false; break; } } void player_CleaningUp(object sender, CleaningUpEventArgs e) { if (!e.CurrentPlayer.Tableau.Contains(this) || e.Actions.ContainsKey(TypeClass.WalledVillage)) return; if (_CanPutOnDeck) e.Actions[TypeClass.WalledVillage] = new CleaningUpAction(this, String.Format("Put {0} on top your deck", this), player_Action); } internal void player_Action(Player player, ref CleaningUpEventArgs e) { e.CardsMovements[this].Destination = DeckLocation.Deck; //e.CardsMovements.MoveToEnd(this); e.CurrentPlayer.RetrieveCardFrom(DeckLocation.Tableau, this); e.CurrentPlayer.AddCardToDeck(this, DeckPosition.Top); } public override void RemovedFrom(DeckLocation location, Player player) { base.RemovedFrom(location, player); if (_PhaseChangingEventHandler != null) player.PhaseChanging -= _PhaseChangingEventHandler; _PhaseChangingEventHandler = null; if (_CleaningUpEventHandler != null) player.CleaningUp -= _CleaningUpEventHandler; _CleaningUpEventHandler = null; _CanPutOnDeck = false; } } }