diff --git a/Mage.Sets/src/mage/cards/h/HamletGlutton.java b/Mage.Sets/src/mage/cards/h/HamletGlutton.java index c7280702bea..2108c8ad0a4 100644 --- a/Mage.Sets/src/mage/cards/h/HamletGlutton.java +++ b/Mage.Sets/src/mage/cards/h/HamletGlutton.java @@ -5,6 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.BargainedCondition; import mage.abilities.costs.CostAdjuster; +import mage.abilities.costs.OptionalAdditionalCost; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.keyword.BargainAbility; @@ -57,9 +58,12 @@ public final class HamletGlutton extends CardImpl { enum HamletGluttonAdjuster implements CostAdjuster { instance; + private static OptionalAdditionalCost bargainCost = BargainAbility.makeBargainCost(); + @Override public void adjustCosts(Ability ability, Game game) { - if (BargainedCondition.instance.apply(game, ability)) { + if (BargainedCondition.instance.apply(game, ability) + || (game.inCheckPlayableState() && bargainCost.canPay(ability, null, ability.getControllerId(), game))) { CardUtil.reduceCost(ability, 2); } } diff --git a/Mage.Sets/src/mage/cards/i/IceOut.java b/Mage.Sets/src/mage/cards/i/IceOut.java index 4fec3375feb..f98ed44b76e 100644 --- a/Mage.Sets/src/mage/cards/i/IceOut.java +++ b/Mage.Sets/src/mage/cards/i/IceOut.java @@ -3,6 +3,7 @@ package mage.cards.i; import mage.abilities.Ability; import mage.abilities.condition.common.BargainedCondition; import mage.abilities.costs.CostAdjuster; +import mage.abilities.costs.OptionalAdditionalCost; import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.keyword.BargainAbility; @@ -48,9 +49,12 @@ public final class IceOut extends CardImpl { enum IceOutAdjuster implements CostAdjuster { instance; + private static OptionalAdditionalCost bargainCost = BargainAbility.makeBargainCost(); + @Override public void adjustCosts(Ability ability, Game game) { - if (BargainedCondition.instance.apply(game, ability)) { + if (BargainedCondition.instance.apply(game, ability) + || (game.inCheckPlayableState() && bargainCost.canPay(ability, null, ability.getControllerId(), game))) { CardUtil.reduceCost(ability, 1); } } diff --git a/Mage.Sets/src/mage/cards/j/JohannsStopgap.java b/Mage.Sets/src/mage/cards/j/JohannsStopgap.java index c976d9e7c74..8f08fa1a1ef 100644 --- a/Mage.Sets/src/mage/cards/j/JohannsStopgap.java +++ b/Mage.Sets/src/mage/cards/j/JohannsStopgap.java @@ -3,6 +3,7 @@ package mage.cards.j; import mage.abilities.Ability; import mage.abilities.condition.common.BargainedCondition; import mage.abilities.costs.CostAdjuster; +import mage.abilities.costs.OptionalAdditionalCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; @@ -50,9 +51,12 @@ public final class JohannsStopgap extends CardImpl { enum JohannsStopgapAdjuster implements CostAdjuster { instance; + private static OptionalAdditionalCost bargainCost = BargainAbility.makeBargainCost(); + @Override public void adjustCosts(Ability ability, Game game) { - if (BargainedCondition.instance.apply(game, ability)) { + if (BargainedCondition.instance.apply(game, ability) + || (game.inCheckPlayableState() && bargainCost.canPay(ability, null, ability.getControllerId(), game))) { CardUtil.reduceCost(ability, 2); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BargainTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BargainTest.java index 8380fef973f..f35e383591e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BargainTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BargainTest.java @@ -42,6 +42,25 @@ public class BargainTest extends CardTestPlayerBase { // 4/4 Artifact private static final String stoneGolem = "Stone Golem"; + /** + * Hamlet Glutton + * {5}{G}{G} + * Creature — Giant + * + * Bargain (You may sacrifice an artifact, enchantment, or token as you cast this spell.) + * + * This spell costs {2} less to cast if it’s bargained. + * + * Trample + * + * When Hamlet Glutton enters the battlefield, you gain 3 life. + * + * 6/6 + */ + private static final String glutton = "Hamlet Glutton"; + + private static final String relic = "Darksteel Relic"; // {0} Artifact + @Test public void testBargainNotPaidOuphe() { setStrictChooseMode(true); @@ -227,4 +246,93 @@ public class BargainTest extends CardTestPlayerBase { assertPermanentCount(playerB, stoneGolem, 0); assertExileCount(playerB, stoneGolem, 1); } + + @Test + public void testBargainOn5ManaGlutton() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + addCard(Zone.HAND, playerA, glutton); + addCard(Zone.HAND, playerA, relic); + + checkPlayableAbility("before relic", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", false); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, relic, true); + + checkPlayableAbility("after relic", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", true); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, glutton, true); + setChoice(playerA, true); // Do bargain. + setChoice(playerA, relic); // Bargain the relic away. + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20 + 3); + } + + @Test + public void testBargainOn7ManaGlutton() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 7); + addCard(Zone.HAND, playerA, glutton); + addCard(Zone.HAND, playerA, relic); + + checkPlayableAbility("before relic", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", true); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, relic, true); + + checkPlayableAbility("after relic", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", true); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, glutton, true); + setChoice(playerA, true); // Do bargain. + setChoice(playerA, relic); // Bargain the relic away. + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20 + 3); + assertTappedCount("Forest", true, 5); + } + + @Test + public void testNoBargainOn7ManaGlutton() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 7); + addCard(Zone.HAND, playerA, glutton); + addCard(Zone.HAND, playerA, relic); + + checkPlayableAbility("before relic", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", true); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, relic, true); + + checkPlayableAbility("after relic", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", true); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, glutton, true); + setChoice(playerA, false); // No bargain. + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20 + 3); + assertTappedCount("Forest", true, 7); + } + + @Test + public void testCantBargainOn7ManaGlutton() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 7); + addCard(Zone.HAND, playerA, glutton); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, glutton, true); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20 + 3); + assertTappedCount("Forest", true, 7); + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/BargainAbility.java b/Mage/src/main/java/mage/abilities/keyword/BargainAbility.java index e60f2821db0..8c4db4df8cc 100644 --- a/Mage/src/main/java/mage/abilities/keyword/BargainAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/BargainAbility.java @@ -49,10 +49,15 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS )); } + public static OptionalAdditionalCost makeBargainCost(){ + OptionalAdditionalCost cost = new OptionalAdditionalCostImpl(keywordText, reminderText, new SacrificeTargetCost(bargainFilter)); + cost.setRepeatable(false); + return cost; + } + public BargainAbility() { super(Zone.STACK, null); - this.additionalCost = new OptionalAdditionalCostImpl(keywordText, reminderText, new SacrificeTargetCost(bargainFilter)); - this.additionalCost.setRepeatable(false); + this.additionalCost = makeBargainCost(); this.rule = additionalCost.getName() + ' ' + additionalCost.getReminderText(); this.setRuleAtTheTop(true); this.addHint(BargainCostWasPaidHint.instance); @@ -111,7 +116,6 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS return activationKey != null && getActivationKey(source, game).equalsIgnoreCase(activationKey); } - /** * TODO: remove with Tag Cost Tracking. * Return activation zcc key for searching spell's settings in source object