diff --git a/Mage.Common/src/mage/view/ManaPoolView.java b/Mage.Common/src/mage/view/ManaPoolView.java index 1c758738721..935653afa5d 100644 --- a/Mage.Common/src/mage/view/ManaPoolView.java +++ b/Mage.Common/src/mage/view/ManaPoolView.java @@ -29,6 +29,9 @@ package mage.view; import java.io.Serializable; +import java.util.concurrent.locks.Condition; + +import mage.ConditionalMana; import mage.players.ManaPool; /** @@ -52,7 +55,14 @@ public class ManaPoolView implements Serializable { this.white = pool.getWhite(); this.black = pool.getBlack(); this.colorless = pool.getColorless(); - + for (ConditionalMana mana : pool.getConditionalMana()) { + this.red = mana.getRed(); + this.green = mana.getGreen(); + this.blue = mana.getBlue(); + this.white = mana.getWhite(); + this.black = mana.getBlack(); + this.colorless = mana.getColorless(); + } } public int getRed() { diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index d5b5ccad711..957842acc4b 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -76,6 +76,8 @@ import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetDefender; +import javax.xml.transform.Source; + /** * * @author BetaSteward_at_googlemail.com @@ -372,7 +374,7 @@ public class HumanPlayer extends PlayerImpl { if (cost instanceof PhyrexianManaCost) { PhyrexianManaCost ph = (PhyrexianManaCost)cost; if (ph.canPay(null, playerId, game)) { - ((PhyrexianManaCost)cost).pay(game, null, playerId, false); + ((PhyrexianManaCost)cost).pay(null, game, null, playerId, false); } break; } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/GhostlyPrison.java b/Mage.Sets/src/mage/sets/championsofkamigawa/GhostlyPrison.java index e58183ddd52..bcd8a5e0209 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/GhostlyPrison.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/GhostlyPrison.java @@ -93,7 +93,7 @@ class GhostlyPrisonReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/GreenhiltTrainee.java b/Mage.Sets/src/mage/sets/newphyrexia/GreenhiltTrainee.java index c6e4ded6778..28af55ae7c5 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/GreenhiltTrainee.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/GreenhiltTrainee.java @@ -101,7 +101,7 @@ class GreenhiltTraineeCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java b/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java index e0c09201b0c..615abfd2f1c 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java @@ -91,7 +91,7 @@ class NornsAnnexReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/Embersmith.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/Embersmith.java index 31f7ef6db2b..2802afa5cc7 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/Embersmith.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/Embersmith.java @@ -93,7 +93,7 @@ class EmbersmithEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Cost cost = new GenericManaCost(1); cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { permanent.damage(1, source.getId(), game, true, false); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java index 31401448991..5451c49be4e 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java @@ -106,7 +106,7 @@ class LeoninArbiterReplacementEffect extends ReplacementEffectImpl { public boolean apply(Game game, Ability source) { Cost cost = new GenericManaCost(1); cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { player.gainLife(3, game); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrBattlesphere.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrBattlesphere.java index 84b86301946..18c4358eac3 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrBattlesphere.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrBattlesphere.java @@ -104,7 +104,7 @@ class MyrBattlesphereAbility extends TriggeredAbilityImpl { public boolean apply(Game game, Ability source) { Cost cost = new GenericManaCost(1); cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { new MyrToken().putOntoBattlefield(game, source.getControllerId(), source.getControllerId()); } return true; diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java index 962c13f9e60..84e7b8a5efd 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java @@ -158,7 +158,7 @@ class NimDeathmantleEffect extends OneShotEffect { if (player != null && equipment != null) { if (player.chooseUse(Constants.Outcome.Benefit, equipment.getName() + " - Pay " + cost.getText() + "?", game)) { cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { UUID target = targetPointer.getFirst(source); if (target != null && equipment != null) { Card card = game.getCard(target); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/PainfulQuandary.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/PainfulQuandary.java index 1178f4038cb..4f70bfb3462 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/PainfulQuandary.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/PainfulQuandary.java @@ -121,7 +121,7 @@ class PainfulQuandryEffect extends OneShotEffect { Player player = game.getPlayer(source.getFirstTarget()); if (player != null) { Cost cost = new DiscardTargetCost(new TargetCardInHand()); - if (!cost.pay(game, player.getId(), player.getId(), false)) { + if (!cost.pay(source, game, player.getId(), player.getId(), false)) { player.loseLife(5, game); } return true; diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/VigilForTheLost.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/VigilForTheLost.java index f4d358360db..224dca33c4c 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/VigilForTheLost.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/VigilForTheLost.java @@ -117,7 +117,7 @@ class VigilForTheLostEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { ManaCostsImpl cost = new ManaCostsImpl("{X}"); cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { Player player = game.getPlayer(source.getControllerId()); player.gainLife(((VariableCost)cost.getVariableCosts().get(0)).getAmount(), game); return true; diff --git a/Mage.Sets/src/mage/sets/shardsofalara/FlameblastDragon.java b/Mage.Sets/src/mage/sets/shardsofalara/FlameblastDragon.java index 95b45d7b681..c258a2ccedd 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/FlameblastDragon.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/FlameblastDragon.java @@ -92,7 +92,7 @@ class FlameblastDragonEffect extends OneShotEffect { if (player != null) { if (player.chooseUse(Constants.Outcome.Damage, "Pay " + cost.getText() + "? If you do, Flameblast Dragon deals X damage to target creature or player", game)) { cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { int costX = ((VariableCost) cost.getVariableCosts().get(0)).getAmount(); Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { diff --git a/Mage.Sets/src/mage/sets/tempest/Propaganda.java b/Mage.Sets/src/mage/sets/tempest/Propaganda.java index 36e4993e0b8..3ea3b8e7911 100644 --- a/Mage.Sets/src/mage/sets/tempest/Propaganda.java +++ b/Mage.Sets/src/mage/sets/tempest/Propaganda.java @@ -93,7 +93,7 @@ class PropagandaReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage/src/mage/ConditionalMana.java b/Mage/src/mage/ConditionalMana.java new file mode 100644 index 00000000000..a3d4509ef02 --- /dev/null +++ b/Mage/src/mage/ConditionalMana.java @@ -0,0 +1,112 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ +package mage; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.filter.Filter; +import mage.game.Game; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantuko + */ +public class ConditionalMana extends Mana implements Serializable { + + /** + * Conditions that should be met (all or any depending on comparison scope) to allow spending {@link Mana} mana. + */ + private List conditions = new ArrayList(); + + /** + * Text displayed as a description for conditional mana. + * Usually includes the conditions that should be met to use this mana. + */ + protected String staticText = "Conditional mana."; + + /** + * By default all conditions should be met + */ + private Filter.ComparisonScope scope = Filter.ComparisonScope.All; + + public ConditionalMana(Mana mana) { + super(mana); + } + + public ConditionalMana(ConditionalMana conditionalMana) { + super(conditionalMana); + conditions = conditionalMana.conditions; + scope = conditionalMana.scope; + staticText = conditionalMana.staticText; + } + + public void addCondition(Condition condition) { + this.conditions.add(condition); + } + + public void setComparisonScope(Filter.ComparisonScope scope) { + this.scope = scope; + } + + public boolean apply(Ability ability, Game game) { + if (conditions.size() == 0) { + throw new IllegalStateException("Conditional mana should contain at least one Condition"); + } + for (Condition condition : conditions) { + if (!condition.apply(game, ability)) { + // if one condition fails, return false only if All conditions should be met + // otherwise it may happen that Any other condition will be ok + if (scope.equals(Filter.ComparisonScope.All)) { + return false; + } + } else { + // if one condition succeeded, return true only if Any conditions should be met + // otherwise it may happen that any other condition will fail + if (scope.equals(Filter.ComparisonScope.Any)) { + return true; + } + } + } + // we are here + // if All conditions should be met, then it's Ok (return true) + // if Any, then it should have already returned true, so returning false here + return scope.equals(Filter.ComparisonScope.All); + } + + @Override + public ConditionalMana copy() { + return new ConditionalMana(this); + } + + public String getDescription() { + return staticText; + } +} diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index f62619ec0fb..c36b5ee66cc 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -174,13 +174,13 @@ public abstract class AbilityImpl> implements Ability { game.getContinuousEffects().costModification(this, game); //20100716 - 601.2f - if (!manaCostsToPay.pay(game, sourceId, controllerId, noMana)) { + if (!manaCostsToPay.pay(this, game, sourceId, controllerId, noMana)) { logger.debug("activate failed - mana"); return false; } } //20100716 - 601.2g - if (!costs.pay(game, sourceId, controllerId, noMana)) { + if (!costs.pay(this, game, sourceId, controllerId, noMana)) { logger.debug("activate failed - non mana costs"); return false; } @@ -194,7 +194,7 @@ public abstract class AbilityImpl> implements Ability { for (AlternativeCost cost: alternativeCosts) { if (cost.isAvailable(game, this)) { if (game.getPlayer(this.controllerId).chooseUse(Outcome.Neutral, "Use alternative cost " + cost.getName(), game)) - return cost.pay(game, sourceId, controllerId, false); + return cost.pay(this, game, sourceId, controllerId, false); } } return false; diff --git a/Mage/src/mage/abilities/costs/CompositeCost.java b/Mage/src/mage/abilities/costs/CompositeCost.java index 3bba19212c8..dd04d8a4a53 100644 --- a/Mage/src/mage/abilities/costs/CompositeCost.java +++ b/Mage/src/mage/abilities/costs/CompositeCost.java @@ -1,5 +1,6 @@ package mage.abilities.costs; +import mage.abilities.Ability; import mage.game.Game; import mage.target.Targets; @@ -33,8 +34,8 @@ public class CompositeCost implements Cost { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { - return firstCost.pay(game, sourceId, controllerId, noMana) && secondCost.pay(game, sourceId, controllerId, noMana); + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + return firstCost.pay(ability, game, sourceId, controllerId, noMana) && secondCost.pay(ability, game, sourceId, controllerId, noMana); } @Override diff --git a/Mage/src/mage/abilities/costs/Cost.java b/Mage/src/mage/abilities/costs/Cost.java index 31005e5fd63..5303b570ed8 100644 --- a/Mage/src/mage/abilities/costs/Cost.java +++ b/Mage/src/mage/abilities/costs/Cost.java @@ -30,6 +30,8 @@ package mage.abilities.costs; import java.io.Serializable; import java.util.UUID; + +import mage.abilities.Ability; import mage.game.Game; import mage.target.Targets; @@ -37,7 +39,7 @@ public interface Cost extends Serializable { public String getText(); public boolean canPay(UUID sourceId, UUID controllerId, Game game); - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana); + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana); public boolean isPaid(); public void clearPaid(); public void setPaid(); diff --git a/Mage/src/mage/abilities/costs/CostsImpl.java b/Mage/src/mage/abilities/costs/CostsImpl.java index cde020b540c..d5614b596bb 100644 --- a/Mage/src/mage/abilities/costs/CostsImpl.java +++ b/Mage/src/mage/abilities/costs/CostsImpl.java @@ -74,11 +74,11 @@ public class CostsImpl extends ArrayList implements Costs } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (this.size() > 0) { while (!isPaid()) { T cost = getFirstUnpaid(); - if (!cost.pay(game, sourceId, controllerId, noMana)) + if (!cost.pay(ability, game, sourceId, controllerId, noMana)) return false; } } diff --git a/Mage/src/mage/abilities/costs/common/ControlPermanentCost.java b/Mage/src/mage/abilities/costs/common/ControlPermanentCost.java index 85b9d2e195a..efd62e6c8dc 100644 --- a/Mage/src/mage/abilities/costs/common/ControlPermanentCost.java +++ b/Mage/src/mage/abilities/costs/common/ControlPermanentCost.java @@ -1,5 +1,6 @@ package mage.abilities.costs.common; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; @@ -25,7 +26,7 @@ public class ControlPermanentCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java b/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java index 5f35893967a..30e8934dece 100644 --- a/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java @@ -53,7 +53,7 @@ public class DiscardSourceCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Player player = game.getPlayer(controllerId); if (player != null) { Card card = player.getHand().get(sourceId, game); diff --git a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java index 98adf2dcdf9..e5de532af4d 100644 --- a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java @@ -30,6 +30,7 @@ package mage.abilities.costs.common; import java.util.UUID; import mage.Constants.Outcome; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.cards.Card; import mage.game.Game; @@ -52,7 +53,7 @@ public class DiscardTargetCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (targets.choose(Outcome.Discard, controllerId, game)) { Player player = game.getPlayer(controllerId); for (UUID targetId: targets.get(0).getTargets()) { diff --git a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java index 6e3297eddc6..fbced62e571 100644 --- a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java @@ -30,6 +30,7 @@ package mage.abilities.costs.common; import mage.Constants; import mage.Constants.Outcome; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.cards.Card; import mage.game.Game; @@ -62,7 +63,7 @@ public class ExileFromGraveCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (targets.choose(Outcome.Exile, controllerId, game)) { Player player = game.getPlayer(controllerId); for (UUID targetId: targets.get(0).getTargets()) { diff --git a/Mage/src/mage/abilities/costs/common/ExileSourceCost.java b/Mage/src/mage/abilities/costs/common/ExileSourceCost.java index c1c50f08b02..623d4f8cac9 100644 --- a/Mage/src/mage/abilities/costs/common/ExileSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileSourceCost.java @@ -29,6 +29,8 @@ package mage.abilities.costs.common; import java.util.UUID; + +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -48,7 +50,7 @@ public class ExileSourceCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { paid = permanent.moveToExile(null, "", sourceId, game); diff --git a/Mage/src/mage/abilities/costs/common/MetalcraftCost.java b/Mage/src/mage/abilities/costs/common/MetalcraftCost.java index b43b0fff4e1..d6708dc6873 100644 --- a/Mage/src/mage/abilities/costs/common/MetalcraftCost.java +++ b/Mage/src/mage/abilities/costs/common/MetalcraftCost.java @@ -30,6 +30,7 @@ package mage.abilities.costs.common; import java.util.UUID; import mage.Constants.CardType; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.filter.FilterPermanent; import mage.game.Game; @@ -65,7 +66,7 @@ public class MetalcraftCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage/src/mage/abilities/costs/common/OnlyDuringUpkeepCost.java b/Mage/src/mage/abilities/costs/common/OnlyDuringUpkeepCost.java index b9df5273d2d..fba957bb498 100644 --- a/Mage/src/mage/abilities/costs/common/OnlyDuringUpkeepCost.java +++ b/Mage/src/mage/abilities/costs/common/OnlyDuringUpkeepCost.java @@ -29,6 +29,7 @@ package mage.abilities.costs.common; import java.util.UUID; import mage.Constants.PhaseStep; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; @@ -59,7 +60,7 @@ public class OnlyDuringUpkeepCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = true; return paid; } diff --git a/Mage/src/mage/abilities/costs/common/PayLifeCost.java b/Mage/src/mage/abilities/costs/common/PayLifeCost.java index 6cbfd270909..3180f8e2f04 100644 --- a/Mage/src/mage/abilities/costs/common/PayLifeCost.java +++ b/Mage/src/mage/abilities/costs/common/PayLifeCost.java @@ -60,7 +60,7 @@ public class PayLifeCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = game.getPlayer(controllerId).loseLife(amount, game) == amount; return paid; } diff --git a/Mage/src/mage/abilities/costs/common/PayLoyaltyCost.java b/Mage/src/mage/abilities/costs/common/PayLoyaltyCost.java index f42148993ad..b1d45348141 100644 --- a/Mage/src/mage/abilities/costs/common/PayLoyaltyCost.java +++ b/Mage/src/mage/abilities/costs/common/PayLoyaltyCost.java @@ -29,6 +29,8 @@ package mage.abilities.costs.common; import java.util.UUID; + +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.counters.CounterType; import mage.game.Game; @@ -62,7 +64,7 @@ public class PayLoyaltyCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent planeswalker = game.getPermanent(sourceId); if (planeswalker.getCounters().getCount(CounterType.LOYALTY) + amount >= 0 && !planeswalker.isLoyaltyUsed()) { if (amount > 0) { diff --git a/Mage/src/mage/abilities/costs/common/PayVariableLoyaltyCost.java b/Mage/src/mage/abilities/costs/common/PayVariableLoyaltyCost.java index 682247b1232..ad724a7ae46 100644 --- a/Mage/src/mage/abilities/costs/common/PayVariableLoyaltyCost.java +++ b/Mage/src/mage/abilities/costs/common/PayVariableLoyaltyCost.java @@ -29,6 +29,8 @@ package mage.abilities.costs.common; import java.util.UUID; + +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.abilities.costs.VariableCost; import mage.counters.CounterType; @@ -60,7 +62,7 @@ public class PayVariableLoyaltyCost extends CostImpl imp } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent planeswalker = game.getPermanent(sourceId); Player player = game.getPlayer(planeswalker.getControllerId()); this.amountPaid = player.getAmount(0, planeswalker.getCounters().getCount(CounterType.LOYALTY), "Choose X", game); diff --git a/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java b/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java index cd86841753d..1c8ef227dd5 100644 --- a/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java @@ -71,7 +71,7 @@ public class RemoveCountersSourceCost extends CostImpl } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null && permanent.getCounters().getCount(name) >= amount) { permanent.removeCounters(name, amount, game); diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandSourceCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandSourceCost.java index 9847a5d120d..34325050047 100644 --- a/Mage/src/mage/abilities/costs/common/ReturnToHandSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandSourceCost.java @@ -31,6 +31,7 @@ package mage.abilities.costs.common; import java.util.UUID; import mage.Constants.Zone; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -49,7 +50,7 @@ public class ReturnToHandSourceCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent == null) return false; diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java index 7f75273d40b..c6d33ac8125 100644 --- a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java @@ -31,6 +31,7 @@ package mage.abilities.costs.common; import java.util.UUID; import mage.Constants.Outcome; import mage.Constants.Zone; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -56,7 +57,7 @@ public class ReturnToHandTargetCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (targets.choose(Outcome.ReturnToHand, controllerId, game)) { for (UUID targetId: targets.get(0).getTargets()) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java b/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java index 4f74f622dfa..87096c540b1 100644 --- a/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java @@ -49,7 +49,7 @@ public class SacrificeSourceCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { paid = permanent.sacrifice(sourceId, game); diff --git a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java index 4e886ade141..657057049a6 100644 --- a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import mage.Constants.Outcome; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -58,7 +59,7 @@ public class SacrificeTargetCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (targets.choose(Outcome.Sacrifice, controllerId, game)) { for (UUID targetId: targets.get(0).getTargets()) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage/src/mage/abilities/costs/common/TapSourceCost.java b/Mage/src/mage/abilities/costs/common/TapSourceCost.java index b868ccec496..463f95e0a15 100644 --- a/Mage/src/mage/abilities/costs/common/TapSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/TapSourceCost.java @@ -49,7 +49,7 @@ public class TapSourceCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { paid = permanent.tap(game); diff --git a/Mage/src/mage/abilities/costs/common/TapTargetCost.java b/Mage/src/mage/abilities/costs/common/TapTargetCost.java index a580cd17735..f81a8cca550 100644 --- a/Mage/src/mage/abilities/costs/common/TapTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/TapTargetCost.java @@ -31,6 +31,7 @@ package mage.abilities.costs.common; import java.util.List; import java.util.UUID; import mage.Constants.Outcome; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -55,7 +56,7 @@ public class TapTargetCost extends CostImpl { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (target.choose(Outcome.Tap, controllerId, game)) { for (UUID targetId: (List)target.getTargets()) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage/src/mage/abilities/costs/common/TapVariableTargetCost.java b/Mage/src/mage/abilities/costs/common/TapVariableTargetCost.java index 74800e52f5b..dc6829c677c 100644 --- a/Mage/src/mage/abilities/costs/common/TapVariableTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/TapVariableTargetCost.java @@ -30,6 +30,7 @@ package mage.abilities.costs.common; import java.util.UUID; import mage.Constants.Outcome; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.abilities.costs.VariableCost; import mage.game.Game; @@ -62,7 +63,7 @@ public class TapVariableTargetCost extends CostImpl imple } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { amountPaid = 0; while (true) { target.clearChosen(); diff --git a/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java b/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java index fde000c6f7e..45978712b60 100644 --- a/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java @@ -30,6 +30,8 @@ package mage.abilities.costs.mana; import mage.Constants.ColoredManaSymbol; import mage.Mana; +import mage.abilities.Ability; +import mage.game.Game; import mage.players.ManaPool; public class ColoredManaCost extends ManaCostImpl { @@ -60,8 +62,8 @@ public class ColoredManaCost extends ManaCostImpl { } @Override - public void assignPayment(ManaPool pool) { - this.assignColored(pool, mana); + public void assignPayment(Game game, Ability ability, ManaPool pool) { + this.assignColored(ability, game, pool, mana); } @Override diff --git a/Mage/src/mage/abilities/costs/mana/GenericManaCost.java b/Mage/src/mage/abilities/costs/mana/GenericManaCost.java index ca7915dbdf1..faaa4871a4a 100644 --- a/Mage/src/mage/abilities/costs/mana/GenericManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/GenericManaCost.java @@ -29,6 +29,8 @@ package mage.abilities.costs.mana; import mage.Mana; +import mage.abilities.Ability; +import mage.game.Game; import mage.players.ManaPool; public class GenericManaCost extends ManaCostImpl { @@ -63,8 +65,8 @@ public class GenericManaCost extends ManaCostImpl { } @Override - public void assignPayment(ManaPool pool) { - this.assignColorless(pool, mana); + public void assignPayment(Game game, Ability ability, ManaPool pool) { + this.assignColorless(ability, game, pool, mana); } @Override diff --git a/Mage/src/mage/abilities/costs/mana/HybridManaCost.java b/Mage/src/mage/abilities/costs/mana/HybridManaCost.java index 1648b9ef39c..cdce18163c0 100644 --- a/Mage/src/mage/abilities/costs/mana/HybridManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/HybridManaCost.java @@ -30,6 +30,8 @@ package mage.abilities.costs.mana; import mage.Constants.ColoredManaSymbol; import mage.Mana; +import mage.abilities.Ability; +import mage.game.Game; import mage.players.ManaPool; public class HybridManaCost extends ManaCostImpl { @@ -64,10 +66,10 @@ public class HybridManaCost extends ManaCostImpl { } @Override - public void assignPayment(ManaPool pool) { - if (assignColored(pool, this.mana1)) + public void assignPayment(Game game, Ability ability, ManaPool pool) { + if (assignColored(ability, game, pool, this.mana1)) return; - assignColored(pool, this.mana2); + assignColored(ability, game, pool, this.mana2); } @Override diff --git a/Mage/src/mage/abilities/costs/mana/ManaCost.java b/Mage/src/mage/abilities/costs/mana/ManaCost.java index 2f04ef7d957..a1b888e9562 100644 --- a/Mage/src/mage/abilities/costs/mana/ManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/ManaCost.java @@ -28,9 +28,11 @@ package mage.abilities.costs.mana; +import mage.abilities.Ability; import mage.abilities.costs.*; import mage.Mana; import mage.abilities.mana.ManaOptions; +import mage.game.Game; import mage.players.ManaPool; public interface ManaCost extends Cost { @@ -38,7 +40,7 @@ public interface ManaCost extends Cost { public int convertedManaCost(); public Mana getMana(); public Mana getPayment(); - public void assignPayment(ManaPool pool); + public void assignPayment(Game game, Ability ability, ManaPool pool); public void setPayment(Mana mana); @Override public String getText(); diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java index 8c44faa5391..651162a251c 100644 --- a/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java +++ b/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java @@ -31,6 +31,7 @@ package mage.abilities.costs.mana; import java.util.UUID; import mage.Constants.ColoredManaSymbol; import mage.Mana; +import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.abilities.mana.ManaOptions; import mage.game.Game; @@ -79,9 +80,11 @@ public abstract class ManaCostImpl> extends CostImpl 0) { this.payment.addBlack(); pool.removeBlack(); @@ -89,6 +92,7 @@ public abstract class ManaCostImpl> extends CostImpl 0) { this.payment.addBlue(); pool.removeBlue(); @@ -96,6 +100,7 @@ public abstract class ManaCostImpl> extends CostImpl 0) { this.payment.addWhite(); pool.removeWhite(); @@ -103,6 +108,7 @@ public abstract class ManaCostImpl> extends CostImpl 0) { this.payment.addGreen(); pool.removeGreen(); @@ -110,6 +116,7 @@ public abstract class ManaCostImpl> extends CostImpl 0) { this.payment.addRed(); pool.removeRed(); @@ -120,8 +127,70 @@ public abstract class ManaCostImpl> extends CostImpl payment.count() && pool.count() > 0) { + private boolean payConditionalRed(Ability ability, Game game, ManaPool pool) { + if (pool.getConditionalRed(ability, game) > 0) { + this.payment.addRed(); + pool.removeConditionalRed(ability, game); + return true; + } + return false; + } + + private boolean payConditionalGreen(Ability ability, Game game, ManaPool pool) { + if (pool.getConditionalGreen(ability, game) > 0) { + this.payment.addGreen(); + pool.removeConditionalGreen(ability, game); + return true; + } + return false; + } + + private boolean payConditionalWhite(Ability ability, Game game, ManaPool pool) { + if (pool.getConditionalWhite(ability, game) > 0) { + this.payment.addWhite(); + pool.removeConditionalWhite(ability, game); + return true; + } + return false; + } + + private boolean payConditionalBlue(Ability ability, Game game, ManaPool pool) { + if (pool.getConditionalBlue(ability, game) > 0) { + this.payment.addBlue(); + pool.removeConditionalBlue(ability, game); + return true; + } + return false; + } + + private boolean payConditionalBlack(Ability ability, Game game, ManaPool pool) { + if (pool.getConditionalBlack(ability, game) > 0) { + this.payment.addBlack(); + pool.removeConditionalBlack(ability, game); + return true; + } + return false; + } + + private boolean payConditionalColorless(Ability ability, Game game, ManaPool pool) { + if (pool.getConditionalColorless(ability, game) > 0) { + this.payment.addColorless(); + pool.removeConditionalColorless(ability, game); + return true; + } + return false; + } + + protected boolean assignColorless(Ability ability, Game game, ManaPool pool, int mana) { + int conditionalCount = pool.getConditionalCount(ability, game); + while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) { + if (payConditionalColorless(ability, game, pool)) continue; + if (payConditionalBlack(ability, game, pool)) continue; + if (payConditionalBlue(ability, game, pool)) continue; + if (payConditionalWhite(ability, game, pool)) continue; + if (payConditionalGreen(ability, game, pool)) continue; + if (payConditionalRed(ability, game, pool)) continue; + if (pool.getColorless() > 0) { this.payment.addColorless(); pool.removeColorless(); @@ -152,6 +221,7 @@ public abstract class ManaCostImpl> extends CostImpl payment.count(); } @@ -189,16 +259,16 @@ public abstract class ManaCostImpl> extends CostImpl extends ArrayList implements ManaCosts { private static Map costs = new HashMap(); - public ManaCostsImpl() {} + public ManaCostsImpl() { + } public ManaCostsImpl(String mana) { load(mana); } public ManaCostsImpl(final ManaCostsImpl costs) { - for (T cost: costs) { - this.add((T)cost.copy()); + for (T cost : costs) { + this.add((T) cost.copy()); } } @Override public boolean add(ManaCost cost) { if (cost instanceof ManaCosts) { - for (ManaCost manaCost: (ManaCosts)cost) { - super.add((T)manaCost); + for (ManaCost manaCost : (ManaCosts) cost) { + super.add((T) manaCost); } return true; - } - else { - return super.add((T)cost); + } else { + return super.add((T) cost); } } @Override public int convertedManaCost() { int total = 0; - for (ManaCost cost: this) { + for (ManaCost cost : this) { total += cost.convertedManaCost(); } return total; @@ -87,7 +84,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public Mana getMana() { Mana mana = new Mana(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { mana.add(cost.getMana()); } return mana; @@ -96,32 +93,32 @@ public class ManaCostsImpl extends ArrayList implements M @Override public Mana getPayment() { Mana manaTotal = new Mana(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { manaTotal.add(cost.getPayment()); } return manaTotal; } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (this.size() == 0 || noMana) { setPaid(); return true; } - + Player player = game.getPlayer(controllerId); - assignPayment(player.getManaPool()); + assignPayment(game, ability, player.getManaPool()); while (!isPaid()) { if (player.playMana(this.getUnpaid(), game)) - assignPayment(player.getManaPool()); + assignPayment(game, ability, player.getManaPool()); else return false; } - for (ManaCost cost: this.getUnpaidVariableCosts()) { + for (ManaCost cost : this.getUnpaidVariableCosts()) { VariableManaCost vCost = (VariableManaCost) cost; while (!vCost.isPaid()) { if (player.playXMana(vCost, (ManaCosts) this, game)) - vCost.assignPayment(player.getManaPool()); + vCost.assignPayment(game, ability, player.getManaPool()); else return false; } @@ -132,9 +129,9 @@ public class ManaCostsImpl extends ArrayList implements M @Override public ManaCosts getUnpaid() { ManaCosts unpaid = new ManaCostsImpl(); - for (T cost: this) { + for (T cost : this) { if (!(cost instanceof VariableManaCost) && !cost.isPaid()) - unpaid.add((T)cost.getUnpaid()); + unpaid.add((T) cost.getUnpaid()); } return unpaid; } @@ -142,9 +139,9 @@ public class ManaCostsImpl extends ArrayList implements M @Override public ManaCosts getUnpaidVariableCosts() { ManaCosts unpaid = new ManaCostsImpl(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (cost instanceof VariableManaCost && !cost.isPaid()) - unpaid.add((T)cost.getUnpaid()); + unpaid.add((T) cost.getUnpaid()); } return unpaid; } @@ -152,7 +149,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public List getVariableCosts() { List variableCosts = new ArrayList(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (cost instanceof VariableCost) variableCosts.add((VariableCost) cost); } @@ -160,39 +157,40 @@ public class ManaCostsImpl extends ArrayList implements M } @Override - public void setPayment(Mana mana) { } + public void setPayment(Mana mana) { + } @Override - public void assignPayment(ManaPool pool) { + public void assignPayment(Game game, Ability ability, ManaPool pool) { //attempt to pay colored costs first - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof ColoredManaCost) { - cost.assignPayment(pool); + cost.assignPayment(game, ability, pool); } } - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof HybridManaCost) { - cost.assignPayment(pool); + cost.assignPayment(game, ability, pool); } } - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof MonoHybridManaCost) { - cost.assignPayment(pool); + cost.assignPayment(game, ability, pool); } } - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof GenericManaCost) { - cost.assignPayment(pool); + cost.assignPayment(game, ability, pool); } } - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof VariableManaCost) { - cost.assignPayment(pool); + cost.assignPayment(game, ability, pool); } } } @@ -202,35 +200,32 @@ public class ManaCostsImpl extends ArrayList implements M this.clear(); if (costs.containsKey(mana)) { ManaCosts savedCosts = costs.get(mana); - for (ManaCost cost: savedCosts) { - this.add((T)cost.copy()); + for (ManaCost cost : savedCosts) { + this.add((T) cost.copy()); } - } - else { + } else { if (mana == null || mana.length() == 0) return; String[] symbols = mana.split("^\\{|\\}\\{|\\}$"); - for (String symbol: symbols) { + for (String symbol : symbols) { if (symbol.length() > 0) { if (symbol.length() == 1 || isNumeric(symbol)) { if (Character.isDigit(symbol.charAt(0))) { - this.add((T)new GenericManaCost(Integer.valueOf(symbol))); - } - else { + this.add((T) new GenericManaCost(Integer.valueOf(symbol))); + } else { if (!symbol.equals("X")) - this.add((T)new ColoredManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)))); + this.add((T) new ColoredManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)))); else - this.add((T)new VariableManaCost()); + this.add((T) new VariableManaCost()); //TODO: handle multiple {X} and/or {Y} symbols } - } - else { + } else { if (Character.isDigit(symbol.charAt(0))) { - this.add((T)new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2)))); + this.add((T) new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2)))); } else if (symbol.contains("P")) { - this.add((T)new PhyrexianManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)))); + this.add((T) new PhyrexianManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)))); } else { - this.add((T)new HybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)), ColoredManaSymbol.lookup(symbol.charAt(2)))); + this.add((T) new HybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)), ColoredManaSymbol.lookup(symbol.charAt(2)))); } } } @@ -239,12 +234,11 @@ public class ManaCostsImpl extends ArrayList implements M } } - private boolean isNumeric ( String symbol ) { + private boolean isNumeric(String symbol) { try { Integer.parseInt(symbol); return true; - } - catch ( NumberFormatException e ) { + } catch (NumberFormatException e) { return false; } } @@ -252,7 +246,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public List getSymbols() { List symbols = new ArrayList(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { symbols.add(cost.getText()); } return symbols; @@ -264,7 +258,7 @@ public class ManaCostsImpl extends ArrayList implements M return ""; StringBuilder sbText = new StringBuilder(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { sbText.append(cost.getText()); } return sbText.toString(); @@ -273,7 +267,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public ManaOptions getOptions() { ManaOptions options = new ManaOptions(); - for (ManaCost cost: this) { + for (ManaCost cost : this) { options.addMana(cost.getOptions()); } return options; @@ -281,7 +275,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public boolean testPay(Mana testMana) { - for (ManaCost cost: this) { + for (ManaCost cost : this) { if (cost.testPay(testMana)) return true; } @@ -290,7 +284,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - for (T cost: this) { + for (T cost : this) { if (!cost.canPay(sourceId, controllerId, game)) return false; } @@ -299,8 +293,8 @@ public class ManaCostsImpl extends ArrayList implements M @Override public boolean isPaid() { - for (T cost: this) { - if (!((T)cost instanceof VariableManaCost) && !cost.isPaid()) + for (T cost : this) { + if (!((T) cost instanceof VariableManaCost) && !cost.isPaid()) return false; } return true; @@ -308,14 +302,14 @@ public class ManaCostsImpl extends ArrayList implements M @Override public void clearPaid() { - for (T cost: this) { + for (T cost : this) { cost.clearPaid(); } } @Override public void setPaid() { - for (T cost: this) { + for (T cost : this) { cost.setPaid(); } } @@ -323,7 +317,7 @@ public class ManaCostsImpl extends ArrayList implements M @Override public Targets getTargets() { Targets targets = new Targets(); - for (T cost: this) { + for (T cost : this) { targets.addAll(cost.getTargets()); } return targets; diff --git a/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java b/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java index 63fc4a06514..5027afad5e5 100644 --- a/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java @@ -30,6 +30,8 @@ package mage.abilities.costs.mana; import mage.Constants.ColoredManaSymbol; import mage.Mana; +import mage.abilities.Ability; +import mage.game.Game; import mage.players.ManaPool; public class MonoHybridManaCost extends ManaCostImpl { @@ -64,9 +66,9 @@ public class MonoHybridManaCost extends ManaCostImpl { } @Override - public void assignPayment(ManaPool pool) { - if (!assignColored(pool, mana)) { - assignColorless(pool, mana2); + public void assignPayment(Game game, Ability ability, ManaPool pool) { + if (!assignColored(ability, game, pool, mana)) { + assignColorless(ability, game, pool, mana2); } } diff --git a/Mage/src/mage/abilities/costs/mana/PhyrexianManaCost.java b/Mage/src/mage/abilities/costs/mana/PhyrexianManaCost.java index 445f249b46c..dfadf4a2eb8 100644 --- a/Mage/src/mage/abilities/costs/mana/PhyrexianManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/PhyrexianManaCost.java @@ -31,6 +31,7 @@ package mage.abilities.costs.mana; import java.util.UUID; import mage.Constants.ColoredManaSymbol; +import mage.abilities.Ability; import mage.game.Game; import mage.players.ManaPool; @@ -49,8 +50,8 @@ public class PhyrexianManaCost extends ColoredManaCost { } @Override - public void assignPayment(ManaPool pool) { - if (assignColored(pool, this.mana)) + public void assignPayment(Game game, Ability ability, ManaPool pool) { + if (assignColored(ability, game, pool, this.mana)) return; } @@ -73,7 +74,7 @@ public class PhyrexianManaCost extends ColoredManaCost { } @Override - public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.paid = game.getPlayer(controllerId).loseLife(2, game) == 2; return paid; } diff --git a/Mage/src/mage/abilities/costs/mana/VariableManaCost.java b/Mage/src/mage/abilities/costs/mana/VariableManaCost.java index 6fb93d79c7f..362716599ed 100644 --- a/Mage/src/mage/abilities/costs/mana/VariableManaCost.java +++ b/Mage/src/mage/abilities/costs/mana/VariableManaCost.java @@ -29,7 +29,9 @@ package mage.abilities.costs.mana; import mage.Mana; +import mage.abilities.Ability; import mage.abilities.costs.VariableCost; +import mage.game.Game; import mage.players.ManaPool; /** @@ -61,9 +63,10 @@ public class VariableManaCost extends ManaCostImpl implements } @Override - public void assignPayment(ManaPool pool) { + public void assignPayment(Game game, Ability ability, ManaPool pool) { payment.add(pool.getMana()); - pool.emptyPool(); + payment.add(pool.getAllConditionalMana(ability, game)); + pool.emptyPoolConditional(ability, game); } @Override diff --git a/Mage/src/mage/abilities/effects/common/BasicManaEffect.java b/Mage/src/mage/abilities/effects/common/BasicManaEffect.java index e2c0cb1fd14..caf329885c0 100644 --- a/Mage/src/mage/abilities/effects/common/BasicManaEffect.java +++ b/Mage/src/mage/abilities/effects/common/BasicManaEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common; +import mage.ConditionalMana; import mage.Mana; import mage.abilities.Ability; import mage.game.Game; @@ -13,6 +14,12 @@ public class BasicManaEffect extends ManaEffect { staticText = "Add " + mana.toString() + " to your mana pool"; } + public BasicManaEffect(ConditionalMana conditionalMana) { + super(); + this.mana = conditionalMana; + staticText = "Add " + mana.toString() + " to your mana pool. " + conditionalMana.getDescription(); + } + public BasicManaEffect(final BasicManaEffect effect) { super(effect); this.mana = effect.mana.copy(); diff --git a/Mage/src/mage/abilities/effects/common/CounterUnlessPaysEffect.java b/Mage/src/mage/abilities/effects/common/CounterUnlessPaysEffect.java index 588084dee6d..5eb963c84e6 100644 --- a/Mage/src/mage/abilities/effects/common/CounterUnlessPaysEffect.java +++ b/Mage/src/mage/abilities/effects/common/CounterUnlessPaysEffect.java @@ -67,7 +67,7 @@ public class CounterUnlessPaysEffect extends OneShotEffect { if (player != null) { if (player.chooseUse(executingEffect.getOutcome(), "Pay " + cost.getText() + " and " + executingEffect.getText(source.getModes().getMode()), game)) { cost.clearPaid(); - if (cost.pay(game, source.getId(), source.getControllerId(), false)) { + if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { return executingEffect.apply(game, source); } } diff --git a/Mage/src/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java b/Mage/src/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java index dc56e0c8262..d588b654359 100644 --- a/Mage/src/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java +++ b/Mage/src/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java @@ -35,7 +35,7 @@ public class SacrificeSourceUnlessPaysEffect extends OneShotEffect> implements Game, Serializa applyEffects(); state.getPlayers().resetPassed(); fireUpdatePlayersEvent(); - state.getRevealed().reset(); + state.getRevealed().reset(); break; } else return; diff --git a/Mage/src/mage/players/ManaPool.java b/Mage/src/mage/players/ManaPool.java index e0f02656496..2f791c35a1b 100644 --- a/Mage/src/mage/players/ManaPool.java +++ b/Mage/src/mage/players/ManaPool.java @@ -29,7 +29,14 @@ package mage.players; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import mage.ConditionalMana; import mage.Mana; +import mage.abilities.Ability; +import mage.game.Game; /** * @@ -44,6 +51,8 @@ public class ManaPool implements Serializable { private int black = 0; private int colorless = 0; + private List conditionalMana = new ArrayList(); + public ManaPool() {} public ManaPool(final ManaPool pool) { @@ -53,6 +62,9 @@ public class ManaPool implements Serializable { this.white = pool.white; this.black = pool.black; this.colorless = pool.colorless; + for (ConditionalMana mana : pool.conditionalMana) { + conditionalMana.add(mana.copy()); + } } public void setRed(int red) { @@ -71,6 +83,26 @@ public class ManaPool implements Serializable { return red; } + public int getConditionalRed(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + boolean hasRed = false; + for (ConditionalMana mana : conditionalMana) { + if (mana.getRed() > 0) { + hasRed = true; + break; + } + } + if (!hasRed) return 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.getRed() > 0 && mana.apply(ability, game)) { + return mana.getRed(); + } + } + return 0; + } + public void setGreen(int green) { this.green = green; } @@ -87,6 +119,26 @@ public class ManaPool implements Serializable { return green; } + public int getConditionalGreen(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + boolean hasGreen = false; + for (ConditionalMana mana : conditionalMana) { + if (mana.getGreen() > 0) { + hasGreen = true; + break; + } + } + if (!hasGreen) return 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.getGreen() > 0 && mana.apply(ability, game)) { + return mana.getGreen(); + } + } + return 0; + } + public void setBlue(int blue) { this.blue = blue; } @@ -103,6 +155,26 @@ public class ManaPool implements Serializable { return blue; } + public int getConditionalBlue(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + boolean hasBlue = false; + for (ConditionalMana mana : conditionalMana) { + if (mana.getBlue() > 0) { + hasBlue = true; + break; + } + } + if (!hasBlue) return 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.getBlue() > 0 && mana.apply(ability, game)) { + return mana.getBlue(); + } + } + return 0; + } + public void setWhite(int white) { this.white = white; } @@ -119,6 +191,26 @@ public class ManaPool implements Serializable { return white; } + public int getConditionalWhite(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + boolean hasWhite = false; + for (ConditionalMana mana : conditionalMana) { + if (mana.getWhite() > 0) { + hasWhite = true; + break; + } + } + if (!hasWhite) return 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.getWhite() > 0 && mana.apply(ability, game)) { + return mana.getWhite(); + } + } + return 0; + } + public void setBlack(int black) { this.black = black; } @@ -135,6 +227,60 @@ public class ManaPool implements Serializable { return black; } + public int getConditionalBlack(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + boolean hasBlack = false; + for (ConditionalMana mana : conditionalMana) { + if (mana.getBlack() > 0) { + hasBlack = true; + break; + } + } + if (!hasBlack) return 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.getBlack() > 0 && mana.apply(ability, game)) { + return mana.getBlack(); + } + } + return 0; + } + + public int getConditionalColorless(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + boolean hasColorless = false; + for (ConditionalMana mana : conditionalMana) { + if (mana.getColorless() > 0) { + hasColorless = true; + break; + } + } + if (!hasColorless) return 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.getColorless() > 0 && mana.apply(ability, game)) { + return mana.getColorless(); + } + } + return 0; + } + + + public int getConditionalCount(Ability ability, Game game) { + if (ability == null || conditionalMana.size() == 0) { + return 0; + } + int count = 0; + for (ConditionalMana mana : conditionalMana) { + if (mana.apply(ability, game)) { + count += mana.count(); + } + } + return count; + } + public void setColorless(int colorless) { this.colorless = colorless; } @@ -159,6 +305,27 @@ public class ManaPool implements Serializable { red = 0; green = 0; colorless = 0; + conditionalMana.clear(); + return total; + } + + public int emptyPoolConditional(Ability ability, Game game) { + int total = count(); + black = 0; + blue = 0; + white = 0; + red = 0; + green = 0; + colorless = 0; + // remove only those mana that can be spent for ability + Iterator it = conditionalMana.iterator(); + while (it.hasNext()) { + ConditionalMana mana = it.next(); + if (mana.apply(ability, game)) { + total += mana.count(); + it.remove(); + } + } return total; } @@ -173,13 +340,27 @@ public class ManaPool implements Serializable { return mana; } + public Mana getAllConditionalMana(Ability ability, Game game) { + Mana mana = new Mana(); + mana.setColorless(getConditionalCount(ability, game)); + return mana; + } + public void changeMana(Mana mana) { - this.black += mana.getBlack(); - this.blue += mana.getBlue(); - this.white += mana.getWhite(); - this.red += mana.getRed(); - this.green += mana.getGreen(); - this.colorless += mana.getColorless(); + if (mana instanceof ConditionalMana) { + this.conditionalMana.add((ConditionalMana)mana); + } else { + this.black += mana.getBlack(); + this.blue += mana.getBlue(); + this.white += mana.getWhite(); + this.red += mana.getRed(); + this.green += mana.getGreen(); + this.colorless += mana.getColorless(); + } + } + + public List getConditionalMana() { + return conditionalMana; } public boolean checkMana(Mana mana) { @@ -207,4 +388,59 @@ public class ManaPool implements Serializable { public ManaPool copy() { return new ManaPool(this); } + + public void removeConditionalBlack(Ability ability, Game game) { + for (ConditionalMana mana : conditionalMana) { + if (mana.getBlack() > 0 && mana.apply(ability, game)) { + mana.setBlack(mana.getBlack() - 1); + break; + } + } + } + + public void removeConditionalBlue(Ability ability, Game game) { + for (ConditionalMana mana : conditionalMana) { + if (mana.getBlue() > 0 && mana.apply(ability, game)) { + mana.setBlue(mana.getBlue() - 1); + break; + } + } + } + + public void removeConditionalWhite(Ability ability, Game game) { + for (ConditionalMana mana : conditionalMana) { + if (mana.getWhite() > 0 && mana.apply(ability, game)) { + mana.setWhite(mana.getWhite() - 1); + break; + } + } + } + + public void removeConditionalGreen(Ability ability, Game game) { + for (ConditionalMana mana : conditionalMana) { + if (mana.getGreen() > 0 && mana.apply(ability, game)) { + mana.setGreen(mana.getGreen() - 1); + break; + } + } + } + + public void removeConditionalRed(Ability ability, Game game) { + for (ConditionalMana mana : conditionalMana) { + if (mana.getRed() > 0 && mana.apply(ability, game)) { + mana.setRed(mana.getRed() - 1); + break; + } + } + } + + public void removeConditionalColorless(Ability ability, Game game) { + for (ConditionalMana mana : conditionalMana) { + if (mana.getColorless() > 0 && mana.apply(ability, game)) { + mana.setColorless(mana.getColorless() - 1); + break; + } + } + } + } diff --git a/Mage/src/mage/util/CardUtil.java b/Mage/src/mage/util/CardUtil.java index 474bcb152f2..d292201136b 100644 --- a/Mage/src/mage/util/CardUtil.java +++ b/Mage/src/mage/util/CardUtil.java @@ -112,4 +112,5 @@ public class CardUtil { public static CopyTokenFunction copyTo(Token target) { return new CopyTokenFunction(target); } + }