diff --git a/Mage.Sets/src/mage/cards/b/Barrowgoyf.java b/Mage.Sets/src/mage/cards/b/Barrowgoyf.java new file mode 100644 index 00000000000..b1b48696e99 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Barrowgoyf.java @@ -0,0 +1,60 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; +import mage.abilities.dynamicvalue.common.SavedDamageValue; +import mage.abilities.effects.common.MillThenPutInHandEffect; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessPlusOneSourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author Plopman + */ +public final class Barrowgoyf extends CardImpl { + + private static final DynamicValue powerValue = CardTypesInGraveyardCount.ALL; + + public Barrowgoyf(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.subtype.add(SubType.LHURGOYF); + + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Barrowgoyf's power is equal to the number of card types among cards in all graveyards and its toughness is equal to that number plus 1. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessPlusOneSourceEffect(powerValue))); + + // Whenever Barrowgoyf deals combat damage to a player, you may mill that many cards. If you do, you may put a creature card from among them into your hand. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new MillThenPutInHandEffect(SavedDamageValue.MANY, StaticFilters.FILTER_CARD_CREATURE) + .setText("you may mill that many cards. If you do, you may put a creature card from among them into your hand") + )); + } + + private Barrowgoyf(final Barrowgoyf card) { + super(card); + } + + @Override + public Barrowgoyf copy() { + return new Barrowgoyf(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java index bd9b838d678..2620821a687 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java @@ -35,6 +35,7 @@ public final class ModernHorizons3Commander extends ExpansionSet { cards.add(new SetCardInfo("Austere Command", 167, Rarity.RARE, mage.cards.a.AustereCommand.class)); cards.add(new SetCardInfo("Azlask, the Swelling Scourge", 5, Rarity.MYTHIC, mage.cards.a.AzlaskTheSwellingScourge.class)); cards.add(new SetCardInfo("Azorius Chancery", 319, Rarity.COMMON, mage.cards.a.AzoriusChancery.class)); + cards.add(new SetCardInfo("Barrowgoyf", 50, Rarity.RARE, mage.cards.b.Barrowgoyf.class)); cards.add(new SetCardInfo("Battlefield Forge", 321, Rarity.RARE, mage.cards.b.BattlefieldForge.class)); cards.add(new SetCardInfo("Bident of Thassa", 177, Rarity.RARE, mage.cards.b.BidentOfThassa.class)); cards.add(new SetCardInfo("Bloodbraid Challenger", 70, Rarity.RARE, mage.cards.b.BloodbraidChallenger.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/m3c/BarrowgoyfTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/m3c/BarrowgoyfTest.java new file mode 100644 index 00000000000..82f5b3dc459 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/m3c/BarrowgoyfTest.java @@ -0,0 +1,88 @@ +package org.mage.test.cards.single.m3c; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.player.TestPlayer; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class BarrowgoyfTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.b.Barrowgoyf Barrowgoyf} {2}{B} + * Deathtouch, Lifelink + * Barrowgoyf's power is equal to the number of card types among cards in all graveyards and its toughness is equal to that number plus 1. + * Whenever Barrowgoyf deals combat damage to a player, you may mill that many cards. If you do, you may put a creature card from among them into your hand. + * * / 1+* + */ + private static final String barrowgoyf = "Barrowgoyf"; + + @Test + public void test_Simple() { + setStrictChooseMode(true); + skipInitShuffling(); + + addCard(Zone.BATTLEFIELD, playerA, barrowgoyf); + addCard(Zone.GRAVEYARD, playerB, "Bitterblossom"); // Tribal Enchantment + addCard(Zone.LIBRARY, playerA, "Baneslayer Angel"); + addCard(Zone.LIBRARY, playerA, "Plains"); + + attack(1, playerA, barrowgoyf, playerB); + setChoice(playerA, "Baneslayer Angel"); // return this to hand. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 20 - 2); + assertGraveyardCount(playerA, 1); + assertHandCount(playerA, "Baneslayer Angel", 1); + assertPowerToughness(playerA, barrowgoyf, 3, 4); + } + + @Test + public void test_Simple_NoReturn() { + setStrictChooseMode(true); + skipInitShuffling(); + + addCard(Zone.BATTLEFIELD, playerA, barrowgoyf); + addCard(Zone.GRAVEYARD, playerB, "Bitterblossom"); // Tribal Enchantment + addCard(Zone.LIBRARY, playerA, "Baneslayer Angel"); + addCard(Zone.LIBRARY, playerA, "Plains"); + + attack(1, playerA, barrowgoyf, playerB); + setChoice(playerA, TestPlayer.CHOICE_SKIP); // decide to not return. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 20 - 2); + assertGraveyardCount(playerA, 2); + assertPowerToughness(playerA, barrowgoyf, 4, 5); + } + + @Test + public void test_Simple_CantReturn() { + setStrictChooseMode(true); + skipInitShuffling(); + + addCard(Zone.BATTLEFIELD, playerA, barrowgoyf); + addCard(Zone.GRAVEYARD, playerB, "Bitterblossom"); // Tribal Enchantment + addCard(Zone.GRAVEYARD, playerB, "Grizzly Bears"); + addCard(Zone.LIBRARY, playerA, "Brainstorm"); + addCard(Zone.LIBRARY, playerA, "Plains"); + addCard(Zone.LIBRARY, playerA, "Invasion of Zendikar"); + + attack(1, playerA, barrowgoyf, playerB); + setChoice(playerA, TestPlayer.CHOICE_SKIP); // decide to not return. There was no choice anyway. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 20 - 3); + assertGraveyardCount(playerA, 3); + assertPowerToughness(playerA, barrowgoyf, 6, 7); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/MillThenPutInHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/MillThenPutInHandEffect.java index 94022af588b..eea07228f4e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/MillThenPutInHandEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/MillThenPutInHandEffect.java @@ -2,6 +2,8 @@ package mage.abilities.effects.common; import mage.abilities.Ability; import mage.abilities.Mode; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -24,7 +26,7 @@ import java.util.stream.Collectors; */ public class MillThenPutInHandEffect extends OneShotEffect { - private final int amount; + private final DynamicValue amount; private final boolean optional; private final int maxAmountReturned; // maximum number of cards returned. e.g. 2 for "up to two" private final FilterCard filter; @@ -63,6 +65,22 @@ public class MillThenPutInHandEffect extends OneShotEffect { } public MillThenPutInHandEffect(int amount, FilterCard filter, Effect otherwiseEffect, boolean optional, int maxReturnedCard) { + this(StaticValue.get(amount), filter, otherwiseEffect, optional, maxReturnedCard); + } + + public MillThenPutInHandEffect(DynamicValue amount, FilterCard filter) { + this(amount, filter, true); + } + + public MillThenPutInHandEffect(DynamicValue amount, FilterCard filter, boolean optional) { + this(amount, filter, null, optional); + } + + public MillThenPutInHandEffect(DynamicValue amount, FilterCard filter, Effect otherwiseEffect, boolean optional) { + this(amount, filter, otherwiseEffect, optional, 1); + } + + public MillThenPutInHandEffect(DynamicValue amount, FilterCard filter, Effect otherwiseEffect, boolean optional, int maxReturnedCard) { super(Outcome.Benefit); this.amount = amount; this.filter = filter; @@ -92,7 +110,8 @@ public class MillThenPutInHandEffect extends OneShotEffect { if (player == null) { return false; } - Cards cards = player.millCards(amount, source, game); + int toMill = amount.calculate(game, source, this); + Cards cards = player.millCards(toMill, source, game); if (cards.isEmpty()) { return applyOtherwiseEffect(game, source); } @@ -132,12 +151,9 @@ public class MillThenPutInHandEffect extends OneShotEffect { return staticText; } StringBuilder sb = new StringBuilder("mill "); - if (amount == 1) { - sb.append("a card. "); - } else { - sb.append(CardUtil.numberToText(amount)); - sb.append(" cards. "); - } + String value = amount.toString(); + sb.append(CardUtil.numberToText(value, "a")); + sb.append(value.equals("1") ? " card" : " cards"); if (optional) { sb.append("You may put "); } else {