diff --git a/Mage.Sets/src/mage/cards/b/BergStrider.java b/Mage.Sets/src/mage/cards/b/BergStrider.java index 8643843243..b6cdb6361b 100644 --- a/Mage.Sets/src/mage/cards/b/BergStrider.java +++ b/Mage.Sets/src/mage/cards/b/BergStrider.java @@ -1,7 +1,6 @@ package mage.cards.b; import mage.MageInt; -import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -14,7 +13,7 @@ import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.game.Game; import mage.target.TargetPermanent; -import mage.watchers.common.ManaSpentToCastWatcher; +import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -47,7 +46,7 @@ public final class BergStrider extends CardImpl { Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); ability.addEffect(new BergStriderEffect()); ability.addTarget(new TargetPermanent(filter)); - this.addAbility(ability); + this.addAbility(ability, new ManaPaidSourceWatcher()); } private BergStrider(final BergStrider card) { @@ -79,15 +78,10 @@ class BergStriderEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - ManaSpentToCastWatcher watcher = game.getState().getWatcher(ManaSpentToCastWatcher.class); - if (watcher == null) { - return false; + if (ManaPaidSourceWatcher.getSnowPaid(source.getSourceId(), game) > 0) { + game.addEffect(new DontUntapInControllersNextUntapStepTargetEffect(), source); + return true; } - Mana payment = watcher.getAndResetLastPayment(source.getSourceId()); - if (payment == null || payment.getSnow() < 1) { - return false; - } - game.addEffect(new DontUntapInControllersNextUntapStepTargetEffect(), source); - return true; + return false; } } diff --git a/Mage.Sets/src/mage/cards/b/BlessingOfFrost.java b/Mage.Sets/src/mage/cards/b/BlessingOfFrost.java index 650b9978e9..37530182fe 100644 --- a/Mage.Sets/src/mage/cards/b/BlessingOfFrost.java +++ b/Mage.Sets/src/mage/cards/b/BlessingOfFrost.java @@ -18,6 +18,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetAmount; import mage.target.common.TargetCreaturePermanentAmount; +import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -33,6 +34,7 @@ public final class BlessingOfFrost extends CardImpl { // Distribute X +1/+1 counters among any number of creatures you control, where X is the amount of {S} spent to cast this spell. Then draw a card for each creature you control with power 4 or greater. this.getSpellAbility().addEffect(new BlessingOfFrostEffect()); + this.getSpellAbility().addWatcher(new ManaPaidSourceWatcher()); } private BlessingOfFrost(final BlessingOfFrost card) { @@ -75,7 +77,7 @@ class BlessingOfFrostEffect extends OneShotEffect { if (player == null) { return false; } - int snow = source.getManaCostsToPay().getUsedManaToPay().getSnow(); + int snow = ManaPaidSourceWatcher.getSnowPaid(source.getId(), game); if (snow > 0) { TargetAmount target = new TargetCreaturePermanentAmount(snow, StaticFilters.FILTER_CONTROLLED_CREATURE); target.setNotTarget(true); diff --git a/Mage.Sets/src/mage/cards/b/BloodOnTheSnow.java b/Mage.Sets/src/mage/cards/b/BloodOnTheSnow.java index fc935680f5..878200fb34 100644 --- a/Mage.Sets/src/mage/cards/b/BloodOnTheSnow.java +++ b/Mage.Sets/src/mage/cards/b/BloodOnTheSnow.java @@ -1,15 +1,13 @@ package mage.cards.b; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.Card; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; @@ -17,9 +15,11 @@ import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import mage.watchers.common.ManaPaidSourceWatcher; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class BloodOnTheSnow extends CardImpl { @@ -43,8 +43,9 @@ public final class BloodOnTheSnow extends CardImpl { this.getSpellAbility().addMode(mode); this.getSpellAbility().appendToRule( "Then return a creature or planeswalker card with mana value X or less" - + " from your graveyard to the battlefield, where X is the amount of {S} spent to cast this spell." + + " from your graveyard to the battlefield, where X is the amount of {S} spent to cast this spell." ); + this.getSpellAbility().addWatcher(new ManaPaidSourceWatcher()); } private BloodOnTheSnow(final BloodOnTheSnow card) { @@ -76,7 +77,7 @@ class BloodOnTheSnowEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - int snow = source.getManaCostsToPay().getUsedManaToPay().getSnow(); + int snow = ManaPaidSourceWatcher.getSnowPaid(source.getId(), game); FilterCard filter = new FilterCard("a creature or planeswalker card with mana value " + snow + " or less from your graveyard"); filter.add(Predicates.or(CardType.CREATURE.getPredicate(), CardType.PLANESWALKER.getPredicate())); filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, snow + 1)); diff --git a/Mage.Sets/src/mage/cards/b/BorealOutrider.java b/Mage.Sets/src/mage/cards/b/BorealOutrider.java index ae4272591f..f639e2aad9 100644 --- a/Mage.Sets/src/mage/cards/b/BorealOutrider.java +++ b/Mage.Sets/src/mage/cards/b/BorealOutrider.java @@ -16,6 +16,7 @@ import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -40,7 +41,7 @@ public final class BorealOutrider extends CardImpl { ), BorealOutriderCondition.instance, "Whenever you cast a creature spell, " + "if {S} of any of that spell's colors was spent to cast it, that creature " + "enters the battlefield with an additional +1/+1 counter on it." - )); + ), new ManaPaidSourceWatcher()); } private BorealOutrider(final BorealOutrider card) { @@ -59,12 +60,7 @@ enum BorealOutriderCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Spell spell = (Spell) source.getEffects().get(0).getValue("spellCast"); - return spell != null - && spell - .getSpellAbility() - .getManaCostsToPay() - .getUsedManaToPay() - .checkSnow(spell.getColor(game)); + return spell != null && ManaPaidSourceWatcher.checkSnowColor(spell, game); } } diff --git a/Mage.Sets/src/mage/cards/f/ForswornPaladin.java b/Mage.Sets/src/mage/cards/f/ForswornPaladin.java new file mode 100644 index 0000000000..517f4fb6f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForswornPaladin.java @@ -0,0 +1,93 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.game.Game; +import mage.game.permanent.token.TreasureToken; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.ManaPaidSourceWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ForswornPaladin extends CardImpl { + + public ForswornPaladin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Menace + this.addAbility(new MenaceAbility()); + + // {1}{B}, {T}, Pay 1 life: Create a Treasure token. + Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new TreasureToken()), new ManaCostsImpl<>("{1}{B}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new PayLifeCost(1)); + this.addAbility(ability); + + // {2}{B}: Target creature gets +2/+0 until end of turn. If mana from a Treasure was spent to activate this ability, that creature also gains deathtouch until end of turn. + ability = new SimpleActivatedAbility( + new BoostTargetEffect(2, 0), new ManaCostsImpl<>("{2}{B}") + ); + ability.addEffect(new ForswornPaladinEffect()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability, new ManaPaidSourceWatcher()); + } + + private ForswornPaladin(final ForswornPaladin card) { + super(card); + } + + @Override + public ForswornPaladin copy() { + return new ForswornPaladin(this); + } +} + +class ForswornPaladinEffect extends OneShotEffect { + + ForswornPaladinEffect() { + super(Outcome.Benefit); + staticText = "If mana from a Treasure was spent to activate this ability, " + + "that creature also gains deathtouch until end of turn."; + } + + private ForswornPaladinEffect(final ForswornPaladinEffect effect) { + super(effect); + } + + @Override + public ForswornPaladinEffect copy() { + return new ForswornPaladinEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (ManaPaidSourceWatcher.getTreasurePaid(source.getId(), game) > 0) { + game.addEffect(new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GravenLore.java b/Mage.Sets/src/mage/cards/g/GravenLore.java index fd9d61cb2b..daf9e0852a 100644 --- a/Mage.Sets/src/mage/cards/g/GravenLore.java +++ b/Mage.Sets/src/mage/cards/g/GravenLore.java @@ -9,6 +9,7 @@ import mage.constants.Outcome; import mage.constants.SuperType; import mage.game.Game; import mage.players.Player; +import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -24,6 +25,7 @@ public final class GravenLore extends CardImpl { // Scry X, where is the amount of {S} spent to cast this spell, then draw three cards. this.getSpellAbility().addEffect(new GravenLoreEffect()); + this.getSpellAbility().addWatcher(new ManaPaidSourceWatcher()); } private GravenLore(final GravenLore card) { @@ -58,7 +60,7 @@ class GravenLoreEffect extends OneShotEffect { if (player == null) { return false; } - int snow = source.getManaCostsToPay().getUsedManaToPay().getSnow(); + int snow = ManaPaidSourceWatcher.getSnowPaid(source.getId(), game); if (snow > 0) { player.scry(snow, source, game); } diff --git a/Mage.Sets/src/mage/cards/h/HiredHexblade.java b/Mage.Sets/src/mage/cards/h/HiredHexblade.java new file mode 100644 index 0000000000..0ce856116e --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HiredHexblade.java @@ -0,0 +1,49 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.TreasureSpentToCastCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.watchers.common.ManaPaidSourceWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HiredHexblade extends CardImpl { + + public HiredHexblade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.WARLOCK); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Hired Hexblade enters the battlefield, if mana from a Treasure was spent to cast it, you draw a card and you lose 1 life. + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), + TreasureSpentToCastCondition.instance, "When {this} enters the battlefield, " + + "if mana from a Treasure was spent to cast it, you draw a card and you lose 1 life." + ); + ability.addEffect(new LoseLifeSourceControllerEffect(1)); + this.addAbility(ability, new ManaPaidSourceWatcher()); + } + + private HiredHexblade(final HiredHexblade card) { + super(card); + } + + @Override + public HiredHexblade copy() { + return new HiredHexblade(this); + } +} diff --git a/Mage.Sets/src/mage/cards/j/JadedSellSword.java b/Mage.Sets/src/mage/cards/j/JadedSellSword.java new file mode 100644 index 0000000000..a66afed466 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JadedSellSword.java @@ -0,0 +1,54 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.TreasureSpentToCastCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.watchers.common.ManaPaidSourceWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JadedSellSword extends CardImpl { + + public JadedSellSword(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.DRAGON); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // When Jaded Sell-Sword enters the battlefield, if mana from a Treasure was spent to cast it, it gains first strike and haste until end of turn. + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + )), TreasureSpentToCastCondition.instance, "When {this} enters the battlefield, " + + "if mana from a Treasure was spent to cast it, it gains first strike and haste until end of turn." + ); + ability.addEffect(new GainAbilitySourceEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + )); + this.addAbility(ability, new ManaPaidSourceWatcher()); + } + + private JadedSellSword(final JadedSellSword card) { + super(card); + } + + @Override + public JadedSellSword copy() { + return new JadedSellSword(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SearchForGlory.java b/Mage.Sets/src/mage/cards/s/SearchForGlory.java index 3b68ecccc2..01207f0d06 100644 --- a/Mage.Sets/src/mage/cards/s/SearchForGlory.java +++ b/Mage.Sets/src/mage/cards/s/SearchForGlory.java @@ -13,6 +13,7 @@ import mage.filter.FilterCard; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.target.common.TargetCardInLibrary; +import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -41,6 +42,7 @@ public final class SearchForGlory extends CardImpl { this.getSpellAbility().addEffect(new GainLifeEffect( SnowManaSpentValue.instance ).setText("You gain 1 life for each {S} spent to cast this spell")); + this.getSpellAbility().addWatcher(new ManaPaidSourceWatcher()); } private SearchForGlory(final SearchForGlory card) { diff --git a/Mage.Sets/src/mage/cards/t/TundraFumarole.java b/Mage.Sets/src/mage/cards/t/TundraFumarole.java index 485f2da03f..7b150189be 100644 --- a/Mage.Sets/src/mage/cards/t/TundraFumarole.java +++ b/Mage.Sets/src/mage/cards/t/TundraFumarole.java @@ -13,6 +13,7 @@ import mage.constants.SuperType; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -65,7 +66,7 @@ class TundraFumaroleEffect extends OneShotEffect { if (player == null) { return false; } - int snow = source.getManaCostsToPay().getUsedManaToPay().getSnow(); + int snow = ManaPaidSourceWatcher.getSnowPaid(source.getId(), game); if (snow > 0) { player.getManaPool().addMana(new Mana(ManaType.COLORLESS, snow), game, source, true); } diff --git a/Mage.Sets/src/mage/sets/AdventuresInTheForgottenRealms.java b/Mage.Sets/src/mage/sets/AdventuresInTheForgottenRealms.java index 2f08d3b9ab..2ec372bc46 100644 --- a/Mage.Sets/src/mage/sets/AdventuresInTheForgottenRealms.java +++ b/Mage.Sets/src/mage/sets/AdventuresInTheForgottenRealms.java @@ -83,6 +83,7 @@ public final class AdventuresInTheForgottenRealms extends ExpansionSet { cards.add(new SetCardInfo("Flumph", 15, Rarity.RARE, mage.cards.f.Flumph.class)); cards.add(new SetCardInfo("Fly", 59, Rarity.UNCOMMON, mage.cards.f.Fly.class)); cards.add(new SetCardInfo("Forest", 278, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forsworn Paladin", 104, Rarity.RARE, mage.cards.f.ForswornPaladin.class)); cards.add(new SetCardInfo("Froghemoth", 184, Rarity.RARE, mage.cards.f.Froghemoth.class)); cards.add(new SetCardInfo("Gloom Stalker", 16, Rarity.COMMON, mage.cards.g.GloomStalker.class)); cards.add(new SetCardInfo("Gnoll Hunter", 185, Rarity.COMMON, mage.cards.g.GnollHunter.class)); @@ -99,6 +100,7 @@ public final class AdventuresInTheForgottenRealms extends ExpansionSet { cards.add(new SetCardInfo("Hama Pashar, Ruin Seeker", 224, Rarity.UNCOMMON, mage.cards.h.HamaPasharRuinSeeker.class)); cards.add(new SetCardInfo("Herald of Hadar", 108, Rarity.COMMON, mage.cards.h.HeraldOfHadar.class)); cards.add(new SetCardInfo("Hill Giant Herdgorger", 187, Rarity.COMMON, mage.cards.h.HillGiantHerdgorger.class)); + cards.add(new SetCardInfo("Hired Hexblade", 109, Rarity.COMMON, mage.cards.h.HiredHexblade.class)); cards.add(new SetCardInfo("Hive of the Eye Tyrant", 258, Rarity.RARE, mage.cards.h.HiveOfTheEyeTyrant.class)); cards.add(new SetCardInfo("Hoarding Ogre", 146, Rarity.COMMON, mage.cards.h.HoardingOgre.class)); cards.add(new SetCardInfo("Hobgoblin Captain", 148, Rarity.COMMON, mage.cards.h.HobgoblinCaptain.class)); @@ -110,6 +112,7 @@ public final class AdventuresInTheForgottenRealms extends ExpansionSet { cards.add(new SetCardInfo("Intrepid Outlander", 191, Rarity.UNCOMMON, mage.cards.i.IntrepidOutlander.class)); cards.add(new SetCardInfo("Island", 266, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iymrith, Desert Doom", 62, Rarity.MYTHIC, mage.cards.i.IymrithDesertDoom.class)); + cards.add(new SetCardInfo("Jaded Sell-Sword", 152, Rarity.COMMON, mage.cards.j.JadedSellSword.class)); cards.add(new SetCardInfo("Kick in the Door", 153, Rarity.COMMON, mage.cards.k.KickInTheDoor.class)); cards.add(new SetCardInfo("Krydle of Baldur's Gate", 226, Rarity.UNCOMMON, mage.cards.k.KrydleOfBaldursGate.class)); cards.add(new SetCardInfo("Lightfoot Rogue", 111, Rarity.UNCOMMON, mage.cards.l.LightfootRogue.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/ManaWasSpentToCastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/ManaWasSpentToCastTest.java index 320bf28ffa..95fe8dc984 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/ManaWasSpentToCastTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/ManaWasSpentToCastTest.java @@ -1,6 +1,8 @@ package org.mage.test.cards.conditional; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.HasteAbility; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Test; @@ -86,4 +88,52 @@ public class ManaWasSpentToCastTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Search for Glory", 1); assertLife(playerA, 21); } + + @Test + public void testSnowMana3() { + addCard(Zone.BATTLEFIELD, playerA, "Snow-Covered Island"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.HAND, playerA, "Berg Strider"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Berg Strider"); + + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + assertAllCommandsUsed(); + + assertTapped("Silvercoat Lion", true); + } + + @Test + public void testTreasureMana() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, "Jaded Sell-Sword"); + addCard(Zone.HAND, playerA, "Strike It Rich", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Strike It Rich"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Jaded Sell-Sword"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertAbility(playerA, "Jaded Sell-Sword", FirstStrikeAbility.getInstance(), true); + assertAbility(playerA, "Jaded Sell-Sword", HasteAbility.getInstance(), true); + } + + @Test + public void testTreasureMana2() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, "Jaded Sell-Sword"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Jaded Sell-Sword"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertAbility(playerA, "Jaded Sell-Sword", FirstStrikeAbility.getInstance(), false); + assertAbility(playerA, "Jaded Sell-Sword", HasteAbility.getInstance(), false); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java index 62a60d0fdf..b57fcb84d0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java @@ -334,7 +334,7 @@ public abstract class CardTestAPIImpl extends MageTestBase implements CardTestAP for (Ability ability : abilities) { Assert.assertTrue("No such ability=" + ability.toString() + ", player=" + player.getName() + - ", cardName" + cardName, found.getAbilities().contains(ability)); + ", cardName=" + cardName, found.getAbilities().contains(ability)); } } diff --git a/Mage/src/main/java/mage/ConditionalMana.java b/Mage/src/main/java/mage/ConditionalMana.java index 1c2cb20991..1d153d9096 100644 --- a/Mage/src/main/java/mage/ConditionalMana.java +++ b/Mage/src/main/java/mage/ConditionalMana.java @@ -113,25 +113,25 @@ public class ConditionalMana extends Mana implements Serializable, Emptiable { return; } if (filter.isBlack()) { - black.clear(); + black = 0; } if (filter.isBlue()) { - blue.clear(); + blue = 0; } if (filter.isWhite()) { - white.clear(); + white = 0; } if (filter.isGreen()) { - green.clear(); + green = 0; } if (filter.isRed()) { - red.clear(); + red = 0; } if (filter.isColorless()) { - colorless.clear(); + colorless = 0; } if (filter.isGeneric()) { - generic.clear(); + generic = 0; } } @@ -154,25 +154,25 @@ public class ConditionalMana extends Mana implements Serializable, Emptiable { public void clear(ManaType manaType) { switch (manaType) { case BLACK: - black.clear(); + black = 0; break; case BLUE: - blue.clear(); + blue = 0; break; case GREEN: - green.clear(); + green = 0; break; case RED: - red.clear(); + red = 0; break; case WHITE: - white.clear(); + white = 0; break; case GENERIC: - generic.clear(); + generic = 0; break; case COLORLESS: - colorless.clear(); + colorless = 0; break; } } @@ -198,25 +198,25 @@ public class ConditionalMana extends Mana implements Serializable, Emptiable { public void add(ManaType manaType, int amount) { switch (manaType) { case BLACK: - black.incrementAmount(amount, false); + black += amount; break; case BLUE: - blue.incrementAmount(amount, false); + blue += amount; break; case GREEN: - green.incrementAmount(amount, false); + green += amount; break; case RED: - red.incrementAmount(amount, false); + red += amount; break; case WHITE: - white.incrementAmount(amount, false); + white += amount; break; case COLORLESS: - colorless.incrementAmount(amount, false); + colorless += amount; break; case GENERIC: - generic.incrementAmount(amount, false); + generic += amount; break; } } diff --git a/Mage/src/main/java/mage/Mana.java b/Mage/src/main/java/mage/Mana.java index 556f5d7c46..0493400e99 100644 --- a/Mage/src/main/java/mage/Mana.java +++ b/Mage/src/main/java/mage/Mana.java @@ -17,124 +17,30 @@ import java.util.Objects; */ public class Mana implements Comparable, Serializable, Copyable { - protected static final class ManaColor implements Serializable { - private int amount = 0; - private int snowAmount = 0; - - private ManaColor() { - } - - protected ManaColor(final ManaColor manaColor) { - this.copyFrom(manaColor); - } - - private ManaColor(int amount) { - this.amount = amount; - } - - protected int getAmount() { - return amount; - } - - protected int getSnowAmount() { - return snowAmount; - } - - protected void incrementAmount() { - incrementAmount(1, false); - } - - protected void incrementAmount(ManaColor manaColor) { - this.amount = CardUtil.overflowInc(this.amount, manaColor.amount); - this.snowAmount = CardUtil.overflowInc(this.snowAmount, manaColor.snowAmount); - } - - protected void incrementAmount(int amount, boolean snow) { - this.amount = CardUtil.overflowInc(this.amount, amount); - if (snow) { - this.snowAmount = CardUtil.overflowInc(this.snowAmount, amount); - } - } - - protected void removeAmount(ManaColor manaColor) { - this.amount = CardUtil.overflowDec(this.amount, manaColor.amount); - this.snowAmount = CardUtil.overflowDec(this.snowAmount, manaColor.snowAmount); - } - - protected void clear() { - amount = 0; - snowAmount = 0; - } - - protected boolean removeOne(ManaColor manaColor) { - if (manaColor.getAmount() < 1) { - return false; - } - if (manaColor.getSnowAmount() > 0) { - manaColor.snowAmount = CardUtil.overflowDec(manaColor.snowAmount, 1); - this.snowAmount = CardUtil.overflowInc(this.snowAmount, 1); - } - manaColor.amount = CardUtil.overflowDec(manaColor.amount, 1); - this.amount = CardUtil.overflowInc(this.amount, 1); - return true; - } - - protected ManaColor copy() { - return new ManaColor(this); - } - - protected void copyFrom(final ManaColor manaColor) { - this.amount = manaColor.amount; - this.snowAmount = manaColor.snowAmount; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ManaColor manaColor = (ManaColor) o; - return amount == manaColor.amount && snowAmount == manaColor.snowAmount; - } - - @Override - public int hashCode() { - return Objects.hash(amount, snowAmount); - } - - @Override - public String toString() { - if (amount != 0 || snowAmount != 0) { - return amount + "/" + snowAmount; - } else { - return ""; - } - } - } - private static final transient Logger logger = Logger.getLogger(Mana.class); - protected ManaColor white; - protected ManaColor blue; - protected ManaColor black; - protected ManaColor red; - protected ManaColor green; - protected ManaColor generic; - protected ManaColor colorless; - protected ManaColor any; + protected int white; + protected int blue; + protected int black; + protected int red; + protected int green; + protected int generic; + protected int colorless; + protected int any; protected boolean flag; /** * Default constructor. Creates a {@link Mana} object with 0 values. */ public Mana() { - white = new ManaColor(); - blue = new ManaColor(); - black = new ManaColor(); - red = new ManaColor(); - green = new ManaColor(); - generic = new ManaColor(); - colorless = new ManaColor(); - any = new ManaColor(); + white = 0; + blue = 0; + black = 0; + red = 0; + green = 0; + generic = 0; + colorless = 0; + any = 0; flag = false; } @@ -152,14 +58,14 @@ public class Mana implements Comparable, Serializable, Copyable { * @param colorless total Colorless mana to have. */ public Mana(final int white, final int blue, final int black, final int red, final int green, final int generic, final int any, final int colorless) { - this.white = new ManaColor(notNegative(white, "White")); - this.blue = new ManaColor(notNegative(blue, "Blue")); - this.black = new ManaColor(notNegative(black, "Black")); - this.red = new ManaColor(notNegative(red, "Red")); - this.green = new ManaColor(notNegative(green, "Green")); - this.generic = new ManaColor(notNegative(generic, "Generic")); - this.colorless = new ManaColor(notNegative(colorless, "Colorless")); - this.any = new ManaColor(notNegative(any, "Any")); + this.white = notNegative(white, "White"); + this.blue = notNegative(blue, "Blue"); + this.black = notNegative(black, "Black"); + this.red = notNegative(red, "Red"); + this.green = notNegative(green, "Green"); + this.generic = notNegative(generic, "Generic"); + this.colorless = notNegative(colorless, "Colorless"); + this.any = notNegative(any, "Any"); this.flag = false; } @@ -171,14 +77,14 @@ public class Mana implements Comparable, Serializable, Copyable { */ public Mana(final Mana mana) { Objects.requireNonNull(mana, "The passed in mana can not be null"); - this.white = mana.white.copy(); - this.blue = mana.blue.copy(); - this.black = mana.black.copy(); - this.red = mana.red.copy(); - this.green = mana.green.copy(); - this.generic = mana.generic.copy(); - this.colorless = mana.colorless.copy(); - this.any = mana.any.copy(); + this.white = mana.white; + this.blue = mana.blue; + this.black = mana.black; + this.red = mana.red; + this.green = mana.green; + this.generic = mana.generic; + this.colorless = mana.colorless; + this.any = mana.any; this.flag = mana.flag; } @@ -194,19 +100,19 @@ public class Mana implements Comparable, Serializable, Copyable { Objects.requireNonNull(color, "The passed in ColoredManaSymbol can not be null"); switch (color) { case W: - white.incrementAmount(); + white = CardUtil.overflowInc(white, 1); break; case U: - blue.incrementAmount(); + blue = CardUtil.overflowInc(blue, 1); break; case B: - black.incrementAmount(); + black = CardUtil.overflowInc(black, 1); break; case R: - red.incrementAmount(); + red = CardUtil.overflowInc(red, 1); break; case G: - green.incrementAmount(); + green = CardUtil.overflowInc(green, 1); break; default: throw new IllegalArgumentException("Unknown mana color: " + color); @@ -218,25 +124,25 @@ public class Mana implements Comparable, Serializable, Copyable { Objects.requireNonNull(manaType, "The passed in ManaType can not be null"); switch (manaType) { case WHITE: - white.incrementAmount(); + white = CardUtil.overflowInc(white, 1); break; case BLUE: - blue.incrementAmount(); + blue = CardUtil.overflowInc(blue, 1); break; case BLACK: - black.incrementAmount(); + black = CardUtil.overflowInc(black, 1); break; case RED: - red.incrementAmount(); + red = CardUtil.overflowInc(red, 1); break; case GREEN: - green.incrementAmount(); + green = CardUtil.overflowInc(green, 1); break; case COLORLESS: - colorless.incrementAmount(); + colorless = CardUtil.overflowInc(colorless, 1); break; case GENERIC: - generic.incrementAmount(); + generic = CardUtil.overflowInc(generic, 1); break; default: throw new IllegalArgumentException("Unknown manaType: " + manaType); @@ -248,25 +154,25 @@ public class Mana implements Comparable, Serializable, Copyable { Objects.requireNonNull(manaType, "The passed in ManaType can not be null"); switch (manaType) { case WHITE: - white.incrementAmount(num, false); + white = CardUtil.overflowInc(white, num); break; case BLUE: - blue.incrementAmount(num, false); + blue = CardUtil.overflowInc(blue, num); break; case BLACK: - black.incrementAmount(num, false); + black = CardUtil.overflowInc(black, num); break; case RED: - red.incrementAmount(num, false); + red = CardUtil.overflowInc(red, num); break; case GREEN: - green.incrementAmount(num, false); + green = CardUtil.overflowInc(green, num); break; case COLORLESS: - colorless.incrementAmount(num, false); + colorless = CardUtil.overflowInc(colorless, num); break; case GENERIC: - generic.incrementAmount(num, false); + generic = CardUtil.overflowInc(generic, num); break; default: throw new IllegalArgumentException("Unknown manaType: " + manaType); @@ -382,14 +288,14 @@ public class Mana implements Comparable, Serializable, Copyable { * @param mana mana to add to this object. */ public void add(final Mana mana) { - white.incrementAmount(mana.white); - blue.incrementAmount(mana.blue); - black.incrementAmount(mana.black); - red.incrementAmount(mana.red); - green.incrementAmount(mana.green); - generic.incrementAmount(mana.generic); - colorless.incrementAmount(mana.colorless); - any.incrementAmount(mana.any); + white = CardUtil.overflowInc(white, mana.white); + blue = CardUtil.overflowInc(blue, mana.blue); + black = CardUtil.overflowInc(black, mana.black); + red = CardUtil.overflowInc(red, mana.red); + green = CardUtil.overflowInc(green, mana.green); + generic = CardUtil.overflowInc(generic, mana.generic); + colorless = CardUtil.overflowInc(colorless, mana.colorless); + any = CardUtil.overflowInc(any, mana.any); } /** @@ -398,31 +304,27 @@ public class Mana implements Comparable, Serializable, Copyable { * @param manaType */ public void increase(ManaType manaType) { - increase(manaType, false); - } - - public void increase(ManaType manaType, boolean isSnow) { switch (manaType) { case WHITE: - white.incrementAmount(1, isSnow); + white = CardUtil.overflowInc(white, 1); break; case BLUE: - blue.incrementAmount(1, isSnow); + blue = CardUtil.overflowInc(blue, 1); break; case BLACK: - black.incrementAmount(1, isSnow); + black = CardUtil.overflowInc(black, 1); break; case RED: - red.incrementAmount(1, isSnow); + red = CardUtil.overflowInc(red, 1); break; case GREEN: - green.incrementAmount(1, isSnow); + green = CardUtil.overflowInc(green, 1); break; case COLORLESS: - colorless.incrementAmount(1, isSnow); + colorless = CardUtil.overflowInc(colorless, 1); break; case GENERIC: - generic.incrementAmount(1, isSnow); + generic = CardUtil.overflowInc(generic, 1); break; } } @@ -431,77 +333,49 @@ public class Mana implements Comparable, Serializable, Copyable { * Increases the White mana by one. */ public void increaseWhite() { - increaseWhite(1, false); - } - - public void increaseWhite(int amount, boolean snow) { - white.incrementAmount(amount, snow); + white = CardUtil.overflowInc(white, 1); } /** * Increases the Blue mana by one. */ public void increaseBlue() { - increaseBlue(1, false); - } - - public void increaseBlue(int amount, boolean snow) { - blue.incrementAmount(amount, snow); + blue = CardUtil.overflowInc(blue, 1); } /** * Increases the Black mana by one. */ public void increaseBlack() { - increaseBlack(1, false); - } - - public void increaseBlack(int amount, boolean snow) { - black.incrementAmount(amount, snow); + black = CardUtil.overflowInc(black, 1); } /** * Increases the Red mana by one. */ public void increaseRed() { - increaseRed(1, false); - } - - public void increaseRed(int amount, boolean snow) { - red.incrementAmount(amount, snow); + red = CardUtil.overflowInc(red, 1); } /** * Increases the Green mana by one. */ public void increaseGreen() { - increaseGreen(1, false); - } - - public void increaseGreen(int amount, boolean snow) { - green.incrementAmount(amount, snow); + green = CardUtil.overflowInc(green, 1); } /** * Increases the Generic mana by one. */ public void increaseGeneric() { - increaseGeneric(1, false); - } - - public void increaseGeneric(int amount, boolean snow) { - generic.incrementAmount(amount, snow); + generic = CardUtil.overflowInc(generic, 1); } /** * Increases the Colorless mana by one. */ public void increaseColorless() { - increaseColorless(1, false); - } - - public void increaseColorless(int amount, boolean snow) { - colorless.incrementAmount(amount, snow); + colorless = CardUtil.overflowInc(colorless, 1); } /** @@ -510,14 +384,14 @@ public class Mana implements Comparable, Serializable, Copyable { * @param mana mana values to subtract */ public void subtract(final Mana mana) { - white.removeAmount(mana.white); - blue.removeAmount(mana.blue); - black.removeAmount(mana.black); - red.removeAmount(mana.red); - green.removeAmount(mana.green); - generic.removeAmount(mana.generic); - colorless.removeAmount(mana.colorless); - any.removeAmount(mana.any); + white = CardUtil.overflowDec(white, mana.white); + blue = CardUtil.overflowDec(blue, mana.blue); + black = CardUtil.overflowDec(black, mana.black); + red = CardUtil.overflowDec(red, mana.red); + green = CardUtil.overflowDec(green, mana.green); + generic = CardUtil.overflowDec(generic, mana.generic); + colorless = CardUtil.overflowDec(colorless, mana.colorless); + any = CardUtil.overflowDec(any, mana.any); } /** @@ -530,39 +404,53 @@ public class Mana implements Comparable, Serializable, Copyable { * colored mana to pay the generic cost */ public void subtractCost(final Mana mana) throws ArithmeticException { - white.removeAmount(mana.white); - blue.removeAmount(mana.blue); - black.removeAmount(mana.black); - red.removeAmount(mana.red); - green.removeAmount(mana.green); - generic.removeAmount(mana.generic); - colorless.removeAmount(mana.colorless); - any.removeAmount(mana.any); + white = CardUtil.overflowDec(white, mana.white); + blue = CardUtil.overflowDec(blue, mana.blue); + black = CardUtil.overflowDec(black, mana.black); + red = CardUtil.overflowDec(red, mana.red); + green = CardUtil.overflowDec(green, mana.green); + generic = CardUtil.overflowDec(generic, mana.generic); + colorless = CardUtil.overflowDec(colorless, mana.colorless); + any = CardUtil.overflowDec(any, mana.any); - while (generic.getAmount() < 0) { - ManaColor oldColorless = generic.copy(); - if (generic.removeOne(white)) { + while (generic < 0) { + int oldColorless = generic; + if (white > 0) { + white = CardUtil.overflowDec(white, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (generic.removeOne(blue)) { + if (blue > 0) { + blue = CardUtil.overflowDec(blue, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (generic.removeOne(black)) { + if (black > 0) { + black = CardUtil.overflowDec(black, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (generic.removeOne(red)) { + if (red > 0) { + red = CardUtil.overflowDec(red, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (generic.removeOne(green)) { + if (green > 0) { + green = CardUtil.overflowDec(green, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (generic.removeOne(colorless)) { + if (colorless > 0) { + colorless = CardUtil.overflowDec(colorless, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (generic.removeOne(any)) { + if (any > 0) { + any = CardUtil.overflowDec(any, 1); + generic = CardUtil.overflowInc(generic, 1); continue; } - if (oldColorless.getAmount() == generic.getAmount()) { + if (oldColorless == generic) { throw new ArithmeticException("Not enough mana to pay colorless"); } } @@ -574,14 +462,14 @@ public class Mana implements Comparable, Serializable, Copyable { * @return the total count of all combined mana. */ public int count() { - return white.getAmount() - + blue.getAmount() - + black.getAmount() - + red.getAmount() - + green.getAmount() - + generic.getAmount() - + colorless.getAmount() - + any.getAmount(); + return white + + blue + + black + + red + + green + + generic + + colorless + + any; } /** @@ -590,12 +478,12 @@ public class Mana implements Comparable, Serializable, Copyable { * @return the total count of all colored mana. */ public int countColored() { - return white.getAmount() - + blue.getAmount() - + black.getAmount() - + red.getAmount() - + green.getAmount() - + any.getAmount(); + return white + + blue + + black + + red + + green + + any; } /** @@ -613,25 +501,25 @@ public class Mana implements Comparable, Serializable, Copyable { } int count = 0; if (filter.isWhite()) { - count = CardUtil.overflowInc(count, white.getAmount()); + count = CardUtil.overflowInc(count, white); } if (filter.isBlue()) { - count = CardUtil.overflowInc(count, blue.getAmount()); + count = CardUtil.overflowInc(count, blue); } if (filter.isBlack()) { - count = CardUtil.overflowInc(count, black.getAmount()); + count = CardUtil.overflowInc(count, black); } if (filter.isRed()) { - count = CardUtil.overflowInc(count, red.getAmount()); + count = CardUtil.overflowInc(count, red); } if (filter.isGreen()) { - count = CardUtil.overflowInc(count, green.getAmount()); + count = CardUtil.overflowInc(count, green); } if (filter.isGeneric()) { - count = CardUtil.overflowInc(count, generic.getAmount()); + count = CardUtil.overflowInc(count, generic); } if (filter.isColorless()) { - count = CardUtil.overflowInc(count, colorless.getAmount()); + count = CardUtil.overflowInc(count, colorless); } return count; } @@ -640,14 +528,14 @@ public class Mana implements Comparable, Serializable, Copyable { * Sets all mana to 0. */ public void clear() { - white.clear(); - blue.clear(); - black.clear(); - red.clear(); - green.clear(); - generic.clear(); - colorless.clear(); - any.clear(); + white = 0; + blue = 0; + black = 0; + red = 0; + green = 0; + generic = 0; + colorless = 0; + any = 0; } /** @@ -658,53 +546,53 @@ public class Mana implements Comparable, Serializable, Copyable { @Override public String toString() { StringBuilder sbMana = new StringBuilder(); - if (generic.getAmount() > 0) { - sbMana.append('{').append(generic.getAmount()).append('}'); + if (generic > 0) { + sbMana.append('{').append(generic).append('}'); } // too many mana - replace by single icon - if (colorless.getAmount() >= 20) { - sbMana.append(colorless.getAmount()).append("{C}"); + if (colorless >= 20) { + sbMana.append(colorless).append("{C}"); } - if (white.getAmount() >= 20) { - sbMana.append(white.getAmount()).append("{W}"); + if (white >= 20) { + sbMana.append(white).append("{W}"); } - if (blue.getAmount() >= 20) { - sbMana.append(blue.getAmount()).append("{U}"); + if (blue >= 20) { + sbMana.append(blue).append("{U}"); } - if (black.getAmount() >= 20) { - sbMana.append(black.getAmount()).append("{B}"); + if (black >= 20) { + sbMana.append(black).append("{B}"); } - if (red.getAmount() >= 20) { - sbMana.append(red.getAmount()).append("{R}"); + if (red >= 20) { + sbMana.append(red).append("{R}"); } - if (green.getAmount() >= 20) { - sbMana.append(green.getAmount()).append("{G}"); + if (green >= 20) { + sbMana.append(green).append("{G}"); } - if (any.getAmount() >= 20) { - sbMana.append(any.getAmount()).append("{Any}"); + if (any >= 20) { + sbMana.append(any).append("{Any}"); } // normal mana - for (int i = 0; i < colorless.getAmount() && colorless.getAmount() < 20; i++) { + for (int i = 0; i < colorless && colorless < 20; i++) { sbMana.append("{C}"); } - for (int i = 0; i < white.getAmount() && white.getAmount() < 20; i++) { + for (int i = 0; i < white && white < 20; i++) { sbMana.append("{W}"); } - for (int i = 0; i < blue.getAmount() && blue.getAmount() < 20; i++) { + for (int i = 0; i < blue && blue < 20; i++) { sbMana.append("{U}"); } - for (int i = 0; i < black.getAmount() && black.getAmount() < 20; i++) { + for (int i = 0; i < black && black < 20; i++) { sbMana.append("{B}"); } - for (int i = 0; i < red.getAmount() && red.getAmount() < 20; i++) { + for (int i = 0; i < red && red < 20; i++) { sbMana.append("{R}"); } - for (int i = 0; i < green.getAmount() && green.getAmount() < 20; i++) { + for (int i = 0; i < green && green < 20; i++) { sbMana.append("{G}"); } - for (int i = 0; i < any.getAmount() && any.getAmount() < 20; i++) { + for (int i = 0; i < any && any < 20; i++) { sbMana.append("{Any}"); } @@ -731,57 +619,57 @@ public class Mana implements Comparable, Serializable, Copyable { public boolean enough(final Mana cost) { Mana compare = cost.copy(); compare.subtract(this); - if (compare.white.getAmount() < 0) { - compare.any.incrementAmount(compare.white); - if (compare.any.getAmount() < 0) { + if (compare.white < 0) { + compare.any = CardUtil.overflowInc(compare.any, compare.white); + if (compare.any < 0) { return false; } - compare.white.clear(); + compare.white = 0; } - if (compare.blue.getAmount() < 0) { - compare.any.incrementAmount(compare.blue); - if (compare.any.getAmount() < 0) { + if (compare.blue < 0) { + compare.any = CardUtil.overflowInc(compare.any, compare.blue); + if (compare.any < 0) { return false; } - compare.blue.clear(); + compare.blue = 0; } - if (compare.black.getAmount() < 0) { - compare.any.incrementAmount(compare.black); - if (compare.any.getAmount() < 0) { + if (compare.black < 0) { + compare.any = CardUtil.overflowInc(compare.any, compare.black); + if (compare.any < 0) { return false; } - compare.black.clear(); + compare.black = 0; } - if (compare.red.getAmount() < 0) { - compare.any.incrementAmount(compare.red); - if (compare.any.getAmount() < 0) { + if (compare.red < 0) { + compare.any = CardUtil.overflowInc(compare.any, compare.red); + if (compare.any < 0) { return false; } - compare.red.clear(); + compare.red = 0; } - if (compare.green.getAmount() < 0) { - compare.any.incrementAmount(compare.green); - if (compare.any.getAmount() < 0) { + if (compare.green < 0) { + compare.any = CardUtil.overflowInc(compare.any, compare.green); + if (compare.any < 0) { return false; } - compare.green.clear(); + compare.green = 0; } - if (compare.colorless.getAmount() < 0) { - compare.any.incrementAmount(compare.colorless); - if (compare.any.getAmount() < 0) { + if (compare.colorless < 0) { + compare.any = CardUtil.overflowInc(compare.any, compare.colorless); + if (compare.any < 0) { return false; } - compare.colorless.clear(); + compare.colorless = 0; } - if (compare.generic.getAmount() < 0) { - compare.generic.incrementAmount(compare.white); - compare.generic.incrementAmount(compare.blue); - compare.generic.incrementAmount(compare.black); - compare.generic.incrementAmount(compare.red); - compare.generic.incrementAmount(compare.green); - compare.generic.incrementAmount(compare.colorless); - compare.generic.incrementAmount(compare.any); - return compare.generic.getAmount() >= 0; + if (compare.generic < 0) { + compare.generic = CardUtil.overflowInc(compare.generic, compare.white); + compare.generic = CardUtil.overflowInc(compare.generic, compare.blue); + compare.generic = CardUtil.overflowInc(compare.generic, compare.black); + compare.generic = CardUtil.overflowInc(compare.generic, compare.red); + compare.generic = CardUtil.overflowInc(compare.generic, compare.green); + compare.generic = CardUtil.overflowInc(compare.generic, compare.colorless); + compare.generic = CardUtil.overflowInc(compare.generic, compare.any); + return compare.generic >= 0; } return true; } @@ -795,71 +683,71 @@ public class Mana implements Comparable, Serializable, Copyable { public Mana needed(final Mana cost) { Mana compare = cost.copy(); compare.subtract(this); - if (compare.white.getAmount() < 0 && compare.any.getAmount() > 0) { - int diff = Math.min(compare.any.getAmount(), Math.abs(compare.white.getAmount())); - compare.any.incrementAmount(-diff, false); - compare.white.incrementAmount(diff, false); + if (compare.white < 0 && compare.any > 0) { + int diff = Math.min(compare.any, Math.abs(compare.white)); + compare.any = CardUtil.overflowDec(compare.any, diff); + compare.white = CardUtil.overflowInc(compare.white, diff); } - if (compare.blue.getAmount() < 0 && compare.any.getAmount() > 0) { - int diff = Math.min(compare.any.getAmount(), Math.abs(compare.blue.getAmount())); - compare.any.incrementAmount(-diff, false); - compare.blue.incrementAmount(diff, false); + if (compare.blue < 0 && compare.any > 0) { + int diff = Math.min(compare.any, Math.abs(compare.blue)); + compare.any = CardUtil.overflowDec(compare.any, diff); + compare.blue = CardUtil.overflowInc(compare.blue, diff); } - if (compare.black.getAmount() < 0 && compare.any.getAmount() > 0) { - int diff = Math.min(compare.any.getAmount(), Math.abs(compare.black.getAmount())); - compare.any.incrementAmount(-diff, false); - compare.black.incrementAmount(diff, false); + if (compare.black < 0 && compare.any > 0) { + int diff = Math.min(compare.any, Math.abs(compare.black)); + compare.any = CardUtil.overflowDec(compare.any, diff); + compare.black = CardUtil.overflowInc(compare.black, diff); } - if (compare.red.getAmount() < 0 && compare.any.getAmount() > 0) { - int diff = Math.min(compare.any.getAmount(), Math.abs(compare.red.getAmount())); - compare.any.incrementAmount(-diff, false); - compare.red.incrementAmount(diff, false); + if (compare.red < 0 && compare.any > 0) { + int diff = Math.min(compare.any, Math.abs(compare.red)); + compare.any = CardUtil.overflowDec(compare.any, diff); + compare.red = CardUtil.overflowInc(compare.red, diff); } - if (compare.green.getAmount() < 0 && compare.any.getAmount() > 0) { - int diff = Math.min(compare.any.getAmount(), Math.abs(compare.green.getAmount())); - compare.any.incrementAmount(-diff, false); - compare.green.incrementAmount(diff, false); + if (compare.green < 0 && compare.any > 0) { + int diff = Math.min(compare.any, Math.abs(compare.green)); + compare.any = CardUtil.overflowDec(compare.any, diff); + compare.green = CardUtil.overflowInc(compare.green, diff); } - if (compare.colorless.getAmount() < 0 && compare.any.getAmount() > 0) { - int diff = Math.min(compare.any.getAmount(), Math.abs(compare.colorless.getAmount())); - compare.any.incrementAmount(-diff, false); - compare.colorless.incrementAmount(diff, false); + if (compare.colorless < 0 && compare.any > 0) { + int diff = Math.min(compare.any, Math.abs(compare.colorless)); + compare.any = CardUtil.overflowDec(compare.any, diff); + compare.colorless = CardUtil.overflowInc(compare.colorless, diff); } - if (compare.generic.getAmount() < 0) { + if (compare.generic < 0) { int remaining = 0; - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.white.getAmount())); - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.blue.getAmount())); - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.black.getAmount())); - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.red.getAmount())); - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.green.getAmount())); - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.colorless.getAmount())); - remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.any.getAmount())); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.white)); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.blue)); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.black)); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.red)); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.green)); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.colorless)); + remaining = CardUtil.overflowInc(remaining, Math.min(0, compare.any)); if (remaining > 0) { - int diff = Math.min(remaining, Math.abs(compare.generic.getAmount())); - compare.generic.incrementAmount(diff, false); + int diff = Math.min(remaining, Math.abs(compare.generic)); + compare.generic = CardUtil.overflowInc(compare.generic, diff); } } Mana needed = new Mana(); - if (compare.white.getAmount() < 0) { - needed.white.removeAmount(compare.white); + if (compare.white < 0) { + needed.white = CardUtil.overflowDec(needed.white, compare.white); } - if (compare.blue.getAmount() < 0) { - needed.blue.removeAmount(compare.blue); + if (compare.blue < 0) { + needed.blue = CardUtil.overflowDec(needed.blue, compare.blue); } - if (compare.black.getAmount() < 0) { - needed.black.removeAmount(compare.black); + if (compare.black < 0) { + needed.black = CardUtil.overflowDec(needed.black, compare.black); } - if (compare.red.getAmount() < 0) { - needed.red.removeAmount(compare.red); + if (compare.red < 0) { + needed.red = CardUtil.overflowDec(needed.red, compare.red); } - if (compare.green.getAmount() < 0) { - needed.green.removeAmount(compare.green); + if (compare.green < 0) { + needed.green = CardUtil.overflowDec(needed.green, compare.green); } - if (compare.colorless.getAmount() < 0) { - needed.colorless.removeAmount(compare.colorless); + if (compare.colorless < 0) { + needed.colorless = CardUtil.overflowDec(needed.colorless, compare.colorless); } - if (compare.generic.getAmount() < 0) { - needed.generic.removeAmount(compare.generic); + if (compare.generic < 0) { + needed.generic = CardUtil.overflowDec(needed.generic, compare.generic); } return needed; } @@ -870,7 +758,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total White mana. */ public int getWhite() { - return white.getAmount(); + return white; } /** @@ -880,8 +768,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param white total White mana. */ public void setWhite(int white) { - this.white.clear(); - this.white.incrementAmount(notNegative(white, "White"), false); + this.white = notNegative(white, "White"); } /** @@ -890,7 +777,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Blue mana. */ public int getBlue() { - return blue.getAmount(); + return blue; } /** @@ -900,8 +787,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param blue total Blue mana. */ public void setBlue(int blue) { - this.blue.clear(); - this.blue.incrementAmount(notNegative(blue, "Blue"), false); + this.blue = notNegative(blue, "Blue"); } /** @@ -910,7 +796,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Black mana. */ public int getBlack() { - return black.getAmount(); + return black; } /** @@ -920,8 +806,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param black total Black mana. */ public void setBlack(int black) { - this.black.clear(); - this.black.incrementAmount(notNegative(black, "Black"), false); + this.black = notNegative(black, "Black"); } /** @@ -930,7 +815,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Red mana. */ public int getRed() { - return red.getAmount(); + return red; } /** @@ -940,8 +825,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param red total Red mana. */ public void setRed(int red) { - this.red.clear(); - this.red.incrementAmount(notNegative(red, "Red"), false); + this.red = notNegative(red, "Red"); } /** @@ -950,7 +834,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Green mana. */ public int getGreen() { - return green.getAmount(); + return green; } /** @@ -960,8 +844,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param green total Green mana. */ public void setGreen(int green) { - this.green.clear(); - this.green.incrementAmount(notNegative(green, "Green"), false); + this.green = notNegative(green, "Green"); } /** @@ -970,7 +853,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Generic mana. */ public int getGeneric() { - return generic.getAmount(); + return generic; } /** @@ -980,8 +863,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param generic total Generic mana. */ public void setGeneric(int generic) { - this.generic.clear(); - this.generic.incrementAmount(notNegative(generic, "Generic"), false); + this.generic = notNegative(generic, "Generic"); } /** @@ -990,7 +872,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Colorless mana. */ public int getColorless() { - return colorless.getAmount(); + return colorless; } /** @@ -1000,8 +882,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param colorless total Colorless mana. */ public void setColorless(int colorless) { - this.colorless.clear(); - this.colorless.incrementAmount(notNegative(colorless, "Colorless"), false); + this.colorless = notNegative(colorless, "Colorless"); } /** @@ -1010,7 +891,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @return total Any mana. */ public int getAny() { - return any.getAmount(); + return any; } /** @@ -1020,31 +901,7 @@ public class Mana implements Comparable, Serializable, Copyable { * @param any total Any mana. */ public void setAny(int any) { - this.any.clear(); - this.any.incrementAmount(notNegative(any, "Any"), false); - } - - public int getSnow() { - return white.getSnowAmount() - + blue.getSnowAmount() - + black.getSnowAmount() - + red.getSnowAmount() - + green.getSnowAmount() - + colorless.getSnowAmount() - + generic.getSnowAmount() - + any.getSnowAmount(); - } - - public boolean checkSnow(ObjectColor color) { - if (color.isWhite() && white.getSnowAmount() > 0) { - return true; - } else if (color.isBlue() && blue.getSnowAmount() > 0) { - return true; - } else if (color.isBlack() && black.getSnowAmount() > 0) { - return true; - } else if (color.isRed() && red.getSnowAmount() > 0) { - return true; - } else return color.isGreen() && green.getSnowAmount() > 0; + this.any = notNegative(any, "Any"); } /** @@ -1066,25 +923,25 @@ public class Mana implements Comparable, Serializable, Copyable { * @return true if this contains any values that mana has */ public boolean contains(final Mana mana) { - if (mana.white.getAmount() > 0 && this.white.getAmount() > 0) { + if (mana.white > 0 && this.white > 0) { return true; } - if (mana.blue.getAmount() > 0 && this.blue.getAmount() > 0) { + if (mana.blue > 0 && this.blue > 0) { return true; } - if (mana.black.getAmount() > 0 && this.black.getAmount() > 0) { + if (mana.black > 0 && this.black > 0) { return true; } - if (mana.red.getAmount() > 0 && this.red.getAmount() > 0) { + if (mana.red > 0 && this.red > 0) { return true; } - if (mana.green.getAmount() > 0 && this.green.getAmount() > 0) { + if (mana.green > 0 && this.green > 0) { return true; } - if (mana.colorless.getAmount() > 0 && this.colorless.getAmount() > 0) { + if (mana.colorless > 0 && this.colorless > 0) { return true; } - return mana.generic.getAmount() > 0 && this.count() > 0; + return mana.generic > 0 && this.count() > 0; } public boolean containsAny(final Mana mana) { @@ -1101,19 +958,19 @@ public class Mana implements Comparable, Serializable, Copyable { * this has */ public boolean containsAny(final Mana mana, boolean includeColorless) { - if (mana.white.getAmount() > 0 && this.white.getAmount() > 0) { + if (mana.white > 0 && this.white > 0) { return true; - } else if (mana.blue.getAmount() > 0 && this.blue.getAmount() > 0) { + } else if (mana.blue > 0 && this.blue > 0) { return true; - } else if (mana.black.getAmount() > 0 && this.black.getAmount() > 0) { + } else if (mana.black > 0 && this.black > 0) { return true; - } else if (mana.red.getAmount() > 0 && this.red.getAmount() > 0) { + } else if (mana.red > 0 && this.red > 0) { return true; - } else if (mana.green.getAmount() > 0 && this.green.getAmount() > 0) { + } else if (mana.green > 0 && this.green > 0) { return true; - } else if (mana.colorless.getAmount() > 0 && this.colorless.getAmount() > 0 && includeColorless) { + } else if (mana.colorless > 0 && this.colorless > 0 && includeColorless) { return true; - } else return mana.any.getAmount() > 0 && this.count() > 0; + } else return mana.any > 0 && this.count() > 0; } /** @@ -1125,20 +982,17 @@ public class Mana implements Comparable, Serializable, Copyable { * in {@link ColoredManaSymbol}. */ public int getColor(final ColoredManaSymbol color) { - if (color == ColoredManaSymbol.W) { - return white.getAmount(); - } - if (color == ColoredManaSymbol.U) { - return blue.getAmount(); - } - if (color == ColoredManaSymbol.B) { - return black.getAmount(); - } - if (color == ColoredManaSymbol.R) { - return red.getAmount(); - } - if (color == ColoredManaSymbol.G) { - return green.getAmount(); + switch (color) { + case W: + return white; + case U: + return blue; + case B: + return black; + case R: + return red; + case G: + return green; } return 0; } @@ -1154,17 +1008,17 @@ public class Mana implements Comparable, Serializable, Copyable { public int get(final ManaType manaType) { switch (manaType) { case WHITE: - return white.getAmount(); + return white; case BLUE: - return blue.getAmount(); + return blue; case BLACK: - return black.getAmount(); + return black; case RED: - return red.getAmount(); + return red; case GREEN: - return green.getAmount(); + return green; case COLORLESS: - return CardUtil.overflowInc(generic.getAmount(), colorless.getAmount()); + return CardUtil.overflowInc(generic, colorless); } return 0; } @@ -1218,14 +1072,14 @@ public class Mana implements Comparable, Serializable, Copyable { * @param mana the mana to set this object to. */ public void setToMana(final Mana mana) { - this.any.copyFrom(mana.any); - this.white.copyFrom(mana.white); - this.blue.copyFrom(mana.blue.copy()); - this.black.copyFrom(mana.black.copy()); - this.red.copyFrom(mana.red.copy()); - this.green.copyFrom(mana.green.copy()); - this.colorless.copyFrom(mana.colorless.copy()); - this.generic.copyFrom(mana.generic.copy()); + this.any = mana.any; + this.white = mana.white; + this.blue = mana.blue; + this.black = mana.black; + this.red = mana.red; + this.green = mana.green; + this.colorless = mana.colorless; + this.generic = mana.generic; //this.flag = mana.flag; } @@ -1236,14 +1090,14 @@ public class Mana implements Comparable, Serializable, Copyable { * @return if the passed in {@link Mana} values are equal to this object. */ public boolean equalManaValue(final Mana mana) { - return this.any.equals(mana.any) - && this.white.equals(mana.white) - && this.blue.equals(mana.blue) - && this.black.equals(mana.black) - && this.red.equals(mana.red) - && this.green.equals(mana.green) - && this.colorless.equals(mana.colorless) - && this.generic.equals(mana.generic); + return this.any == mana.any + && this.white == mana.white + && this.blue == mana.blue + && this.black == mana.black + && this.red == mana.red + && this.green == mana.green + && this.colorless == mana.colorless + && this.generic == mana.generic; } /** @@ -1256,14 +1110,14 @@ public class Mana implements Comparable, Serializable, Copyable { * {@link Mana}. */ public boolean includesMana(Mana mana) { - return this.white.getAmount() >= mana.white.getAmount() - && this.blue.getAmount() >= mana.blue.getAmount() - && this.black.getAmount() >= mana.black.getAmount() - && this.red.getAmount() >= mana.red.getAmount() - && this.green.getAmount() >= mana.green.getAmount() - && this.colorless.getAmount() >= mana.colorless.getAmount() - && (this.generic.getAmount() >= mana.generic.getAmount() - || CardUtil.overflowInc(this.countColored(), this.colorless.getAmount()) >= mana.count()); + return this.white >= mana.white + && this.blue >= mana.blue + && this.black >= mana.black + && this.red >= mana.red + && this.green >= mana.green + && this.colorless >= mana.colorless + && (this.generic >= mana.generic + || CardUtil.overflowInc(this.countColored(), this.colorless) >= mana.count()); } @@ -1346,20 +1200,20 @@ public class Mana implements Comparable, Serializable, Copyable { */ public int getDifferentColors() { int count = 0; - if (white.getAmount() > 0) { - count++; + if (white > 0) { + count = CardUtil.overflowInc(count, 1); } - if (blue.getAmount() > 0) { - count++; + if (blue > 0) { + count = CardUtil.overflowInc(count, 1); } - if (black.getAmount() > 0) { - count++; + if (black > 0) { + count = CardUtil.overflowInc(count, 1); } - if (red.getAmount() > 0) { - count++; + if (red > 0) { + count = CardUtil.overflowInc(count, 1); } - if (green.getAmount() > 0) { - count++; + if (green > 0) { + count = CardUtil.overflowInc(count, 1); } return count; } @@ -1372,14 +1226,14 @@ public class Mana implements Comparable, Serializable, Copyable { } Mana mana = (Mana) o; return flag == mana.flag - && Objects.equals(white, mana.white) - && Objects.equals(blue, mana.blue) - && Objects.equals(black, mana.black) - && Objects.equals(red, mana.red) - && Objects.equals(green, mana.green) - && Objects.equals(generic, mana.generic) - && Objects.equals(colorless, mana.colorless) - && Objects.equals(any, mana.any); + && white == mana.white + && blue == mana.blue + && black == mana.black + && red == mana.red + && green == mana.green + && generic == mana.generic + && colorless == mana.colorless + && any == mana.any; } @Override diff --git a/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java new file mode 100644 index 0000000000..11035124bd --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java @@ -0,0 +1,22 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.constants.AbilityType; +import mage.game.Game; +import mage.watchers.common.ManaPaidSourceWatcher; + +/** + * @author TheElk801 + */ +public enum TreasureSpentToCastCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + if (source.getAbilityType() == AbilityType.SPELL) { + return ManaPaidSourceWatcher.getTreasurePaid(source.getId(), game) > 0; + } + return ManaPaidSourceWatcher.getTreasurePaid(source.getSourceId(), game) > 0; + } +} diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java index 2848529896..421ce7baae 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java @@ -103,31 +103,31 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { switch (mana) { case W: if (pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseWhite(1, pool.getLastPaymentWasSnow()); + this.payment.increaseWhite(); return true; } break; case U: if (pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseBlue(1, pool.getLastPaymentWasSnow()); + this.payment.increaseBlue(); return true; } break; case B: if (pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseBlack(1, pool.getLastPaymentWasSnow()); + this.payment.increaseBlack(); return true; } break; case R: if (pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseRed(1, pool.getLastPaymentWasSnow()); + this.payment.increaseRed(); return true; } break; case G: if (pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseGreen(1, pool.getLastPaymentWasSnow()); + this.payment.increaseGreen(); return true; } break; @@ -139,7 +139,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { int conditionalCount = pool.getConditionalCount(ability, game, null, costToPay); while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) { if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseColorless(1, pool.getLastPaymentWasSnow()); + this.payment.increaseColorless(); } break; } @@ -155,7 +155,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { if ((filterMana == null || filterMana.isColorless()) && pool.pay( ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay )) { - this.payment.increaseColorless(1, pool.getLastPaymentWasSnow()); + this.payment.increaseColorless(); continue; } @@ -163,7 +163,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { if ((filterMana == null || filterMana.isBlack()) && pool.pay( ManaType.BLACK, ability, sourceFilter, game, costToPay, usedManaToPay )) { - this.payment.increaseBlack(1, pool.getLastPaymentWasSnow()); + this.payment.increaseBlack(); continue; } @@ -171,7 +171,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { if ((filterMana == null || filterMana.isBlue()) && pool.pay( ManaType.BLUE, ability, sourceFilter, game, costToPay, usedManaToPay )) { - this.payment.increaseBlue(1, pool.getLastPaymentWasSnow()); + this.payment.increaseBlue(); continue; } @@ -179,7 +179,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { if ((filterMana == null || filterMana.isWhite()) && pool.pay( ManaType.WHITE, ability, sourceFilter, game, costToPay, usedManaToPay )) { - this.payment.increaseWhite(1, pool.getLastPaymentWasSnow()); + this.payment.increaseWhite(); continue; } @@ -187,7 +187,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { if ((filterMana == null || filterMana.isGreen()) && pool.pay( ManaType.GREEN, ability, sourceFilter, game, costToPay, usedManaToPay )) { - this.payment.increaseGreen(1, pool.getLastPaymentWasSnow()); + this.payment.increaseGreen(); continue; } @@ -195,7 +195,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { if ((filterMana == null || filterMana.isRed()) && pool.pay( ManaType.RED, ability, sourceFilter, game, costToPay, usedManaToPay )) { - this.payment.increaseRed(1, pool.getLastPaymentWasSnow()); + this.payment.increaseRed(); continue; } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SnowManaSpentValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SnowManaSpentValue.java index 5421bf2caf..ca380461cd 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SnowManaSpentValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SnowManaSpentValue.java @@ -1,12 +1,11 @@ package mage.abilities.dynamicvalue.common; -import mage.Mana; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.constants.AbilityType; import mage.game.Game; -import mage.watchers.common.ManaSpentToCastWatcher; +import mage.watchers.common.ManaPaidSourceWatcher; /** * @author TheElk801 @@ -17,17 +16,9 @@ public enum SnowManaSpentValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { if (sourceAbility.getAbilityType() == AbilityType.SPELL) { - return sourceAbility.getManaCostsToPay().getUsedManaToPay().getSnow(); + return ManaPaidSourceWatcher.getSnowPaid(sourceAbility.getId(), game); } - ManaSpentToCastWatcher watcher = game.getState().getWatcher(ManaSpentToCastWatcher.class); - if (watcher == null) { - return 0; - } - Mana payment = watcher.getAndResetLastPayment(sourceAbility.getSourceId()); - if (payment == null) { - return 0; - } - return payment.getSnow(); + return ManaPaidSourceWatcher.getSnowPaid(sourceAbility.getSourceId(), game); } @Override diff --git a/Mage/src/main/java/mage/game/events/ManaPaidEvent.java b/Mage/src/main/java/mage/game/events/ManaPaidEvent.java index 4c34abd239..58e0150838 100644 --- a/Mage/src/main/java/mage/game/events/ManaPaidEvent.java +++ b/Mage/src/main/java/mage/game/events/ManaPaidEvent.java @@ -1,6 +1,8 @@ package mage.game.events; +import mage.MageObject; import mage.abilities.Ability; +import mage.constants.ManaType; import java.util.UUID; @@ -9,9 +11,28 @@ import java.util.UUID; */ public class ManaPaidEvent extends GameEvent { - public ManaPaidEvent(Ability abilityToPay, UUID manaSourceId, boolean manaFlag, UUID manaOriginalId) { + private final UUID sourcePaidId; + private final MageObject sourceObject; + private final ManaType manaType; + + public ManaPaidEvent(Ability abilityToPay, UUID manaSourceId, boolean manaFlag, UUID manaOriginalId, MageObject sourceObject, ManaType manaType) { super(GameEvent.EventType.MANA_PAID, abilityToPay.getId(), null, abilityToPay.getControllerId(), 0, manaFlag); this.setSourceId(manaSourceId); this.setData(manaOriginalId.toString()); + this.sourcePaidId = abilityToPay.getSourceId(); + this.sourceObject = sourceObject; + this.manaType = manaType; + } + + public UUID getSourcePaidId() { + return sourcePaidId; + } + + public MageObject getSourceObject() { + return sourceObject; + } + + public ManaType getManaType() { + return manaType; } } diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index a68d1edc4f..0798ed1bf3 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -50,15 +50,12 @@ public class ManaPool implements Serializable { } } - private boolean lastPaymentWasSnow; - public ManaPool(UUID playerId) { this.playerId = playerId; autoPayment = true; autoPaymentRestricted = true; unlockedManaType = null; forcedToPay = false; - lastPaymentWasSnow = false; } public ManaPool(final ManaPool pool) { @@ -74,7 +71,6 @@ public class ManaPool implements Serializable { poolBookmark.add(item.copy()); } this.doNotEmptyManaTypes.addAll(pool.doNotEmptyManaTypes); - this.lastPaymentWasSnow = pool.lastPaymentWasSnow; this.manaBecomesColorless = pool.manaBecomesColorless; } @@ -109,7 +105,6 @@ public class ManaPool implements Serializable { * @return */ public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, Mana usedManaToPay) { - lastPaymentWasSnow = false; if (!isAutoPayment() && manaType != unlockedManaType) { // if manual payment and the needed mana type was not unlocked, nothing will be paid return false; @@ -139,7 +134,6 @@ public class ManaPool implements Serializable { lockManaType(); // pay only one mana if mana payment is set to manually return true; } - lastPaymentWasSnow = false; for (ManaPoolItem mana : manaItems) { if (filter != null) { @@ -164,11 +158,10 @@ public class ManaPool implements Serializable { continue; } if (mana.get(usableManaType) > 0) { - GameEvent event = new ManaPaidEvent(ability, mana.getSourceId(), mana.getFlag(), mana.getOriginalId()); + GameEvent event = new ManaPaidEvent(ability, mana.getSourceId(), mana.getFlag(), mana.getOriginalId(), mana.getSourceObject(), usableManaType); game.fireEvent(event); - usedManaToPay.increase(usableManaType, mana.getSourceObject().isSnow()); + usedManaToPay.increase(usableManaType); mana.remove(usableManaType); - lastPaymentWasSnow |= mana.getSourceObject().isSnow(); if (mana.count() == 0) { // so no items with count 0 stay in list manaItems.remove(mana); } @@ -410,8 +403,8 @@ public class ManaPool implements Serializable { for (ConditionalMana mana : getConditionalMana()) { if (mana.get(manaInfo.manaType) > 0 && mana.apply(ability, game, mana.getManaProducerId(), costToPay)) { mana.set(manaInfo.manaType, CardUtil.overflowDec(mana.get(manaInfo.manaType), 1)); - usedManaToPay.increase(manaInfo.manaType, manaInfo.sourceObject.isSnow()); - GameEvent event = new ManaPaidEvent(ability, mana.getManaProducerId(), mana.getFlag(), mana.getManaProducerOriginalId()); + usedManaToPay.increase(manaInfo.manaType); + GameEvent event = new ManaPaidEvent(ability, mana.getManaProducerId(), mana.getFlag(), mana.getManaProducerOriginalId(), manaInfo.sourceObject, manaInfo.manaType); game.fireEvent(event); break; } @@ -528,10 +521,6 @@ public class ManaPool implements Serializable { } } - public boolean getLastPaymentWasSnow() { - return lastPaymentWasSnow; - } - @Override public String toString() { return getMana().toString(); diff --git a/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java b/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java new file mode 100644 index 0000000000..9305ebfaf2 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java @@ -0,0 +1,123 @@ +package mage.watchers.common; + +import mage.MageObject; +import mage.ObjectColor; +import mage.constants.ManaType; +import mage.constants.SubType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ManaPaidEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.stack.Spell; +import mage.watchers.Watcher; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public class ManaPaidSourceWatcher extends Watcher { + + private static final class ManaPaidTracker implements Serializable { + private int whiteSnow = 0; + private int blueSnow = 0; + private int blackSnow = 0; + private int redSnow = 0; + private int greenSnow = 0; + private int colorlessSnow = 0; + private int treasure = 0; + + private void increment(MageObject sourceObject, ManaType manaType, Game game) { + if (sourceObject.hasSubtype(SubType.TREASURE, game)) { + treasure++; + } + if (!sourceObject.isSnow()) { + return; + } + switch (manaType) { + case WHITE: + whiteSnow++; + break; + case BLUE: + blueSnow++; + break; + case BLACK: + blackSnow++; + break; + case RED: + redSnow++; + break; + case GREEN: + greenSnow++; + break; + case COLORLESS: + case GENERIC: + colorlessSnow++; + break; + } + } + + private int getSnow() { + return whiteSnow + blueSnow + blackSnow + redSnow + greenSnow + colorlessSnow; + } + + private boolean checkSnowColor(Spell spell, Game game) { + ObjectColor color = spell.getColor(game); + return color.isWhite() && whiteSnow > 0 + || color.isBlue() && blueSnow > 0 + || color.isBlack() && blackSnow > 0 + || color.isRed() && redSnow > 0 + || color.isGreen() && greenSnow > 0; + } + } + + private static final ManaPaidTracker emptyTracker = new ManaPaidTracker(); + private final Map manaMap = new HashMap<>(); + + public ManaPaidSourceWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + switch (event.getType()) { + case ZONE_CHANGE: + if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { + manaMap.remove(event.getSourceId()); + } + return; + case MANA_PAID: + ManaPaidEvent manaEvent = (ManaPaidEvent) event; + manaMap.computeIfAbsent(manaEvent.getTargetId(), x -> new ManaPaidTracker()) + .increment(manaEvent.getSourceObject(), manaEvent.getManaType(), game); + manaMap.computeIfAbsent(manaEvent.getSourcePaidId(), x -> new ManaPaidTracker()) + .increment(manaEvent.getSourceObject(), manaEvent.getManaType(), game); + } + } + + @Override + public void reset() { + super.reset(); + manaMap.clear(); + } + + public static int getTreasurePaid(UUID sourceId, Game game) { + ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class); + return watcher == null ? 0 : watcher.manaMap.getOrDefault(sourceId, emptyTracker).treasure; + } + + public static int getSnowPaid(UUID sourceId, Game game) { + ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class); + return watcher == null ? 0 : watcher.manaMap.getOrDefault(sourceId, emptyTracker).getSnow(); + } + + public static boolean checkSnowColor(Spell spell, Game game) { + ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class); + return watcher != null && watcher.manaMap.getOrDefault(spell.getSpellAbility().getId(), emptyTracker).checkSnowColor(spell, game); + } +}