diff --git a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java index ad53df9520a..98adf2dcdf9 100644 --- a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java @@ -67,7 +67,7 @@ public class DiscardTargetCost extends CostImpl { @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - return targets.canChoose(controllerId, controllerId, game); + return targets.canChoose(controllerId, game); } @Override diff --git a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java index 6cf56898b88..4e886ade141 100644 --- a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java @@ -73,7 +73,7 @@ public class SacrificeTargetCost extends CostImpl { @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - return targets.canChoose(controllerId, controllerId, game); + return targets.canChoose(controllerId, game); } @Override diff --git a/Mage/src/mage/target/Target.java b/Mage/src/mage/target/Target.java index d02e3716592..373d55a123b 100644 --- a/Mage/src/mage/target/Target.java +++ b/Mage/src/mage/target/Target.java @@ -48,21 +48,28 @@ public interface Target extends Serializable { public boolean doneChosing(); public void clearChosen(); public boolean isNotTarget(); + + // methods for targets public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game); public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game); - public boolean choose(Outcome outcome, UUID playerId, Game game); public boolean chooseTarget(Outcome outcome, UUID playerId, Ability source, Game game); + public void addTarget(UUID id, Ability source, Game game); + public void addTarget(UUID id, int amount, Ability source, Game game); + public boolean canTarget(UUID id, Game game); + public boolean canTarget(UUID id, Ability source, Game game); + public boolean isLegal(Ability source, Game game); + + //methods for non-targets + public boolean canChoose(UUID sourceControllerId, Game game); + public Set possibleTargets(UUID sourceControllerId, Game game); + public boolean choose(Outcome outcome, UUID playerId, Game game); + public void add(UUID id, Game game); + public String getMessage(); public String getTargetName(); public void setTargetName(String name); public String getTargetedName(Game game); public Zone getZone(); - public boolean isLegal(Ability source, Game game); - public boolean canTarget(UUID id, Game game); - public boolean canTarget(UUID id, Ability source, Game game); - public void add(UUID id, Game game); - public void addTarget(UUID id, Ability source, Game game); - public void addTarget(UUID id, int amount, Ability source, Game game); public int getTargetAmount(UUID targetId); public int getNumberOfTargets(); diff --git a/Mage/src/mage/target/TargetCard.java b/Mage/src/mage/target/TargetCard.java index 6e5450e84e7..da2d9709257 100644 --- a/Mage/src/mage/target/TargetCard.java +++ b/Mage/src/mage/target/TargetCard.java @@ -76,8 +76,28 @@ public class TargetCard> extends TargetObject> extends TargetObject possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + return possibleTargets(sourceControllerId, game); + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); Player player = game.getPlayer(sourceControllerId); if (player != null) { diff --git a/Mage/src/mage/target/TargetPermanent.java b/Mage/src/mage/target/TargetPermanent.java index ed3a1e7d04d..3af17a7ed44 100644 --- a/Mage/src/mage/target/TargetPermanent.java +++ b/Mage/src/mage/target/TargetPermanent.java @@ -94,6 +94,15 @@ public class TargetPermanent> extends TargetObject< return this.filter; } + /** + * Checks if there are enough {@link Permanent} that can be chosen. Should only be used + * for Ability targets since this checks for protection, shroud etc. + * + * @param sourceId - the target event source + * @param sourceControllerId - controller of the target event source + * @param game + * @return - true if enough valid {@link Permanent} exist + */ @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { int count = 0; @@ -108,6 +117,19 @@ public class TargetPermanent> extends TargetObject< return false; } + /** + * Checks if there are enough {@link Permanent} that can be selected. Should not be used + * for Ability targets since this does not check for protection, shroud etc. + * + * @param sourceControllerId - controller of the select event + * @param game + * @return - true if enough valid {@link Permanent} exist + */ + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + return game.getBattlefield().count(filter, sourceControllerId, game) >= this.minNumberOfTargets; + } + @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); @@ -120,6 +142,15 @@ public class TargetPermanent> extends TargetObject< return possibleTargets; } + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet(); + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + return possibleTargets; + } + @Override public TargetPermanent copy() { return new TargetPermanent(this); diff --git a/Mage/src/mage/target/TargetPlayer.java b/Mage/src/mage/target/TargetPlayer.java index d88833a5347..334b2d368db 100644 --- a/Mage/src/mage/target/TargetPlayer.java +++ b/Mage/src/mage/target/TargetPlayer.java @@ -70,6 +70,15 @@ public class TargetPlayer> extends TargetImpl> extends TargetImpl= this.minNumberOfTargets) + return true; + } + } + return false; + } + @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); @@ -101,6 +132,18 @@ public class TargetPlayer> extends TargetImpl possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet(); + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && !player.hasLeft() && filter.match(player)) { + possibleTargets.add(playerId); + } + } + return possibleTargets; + } + @Override public boolean isLegal(Ability source, Game game) { for (UUID playerId: targets.keySet()) { diff --git a/Mage/src/mage/target/TargetSpell.java b/Mage/src/mage/target/TargetSpell.java index 42cce3df6eb..889da3ceae8 100644 --- a/Mage/src/mage/target/TargetSpell.java +++ b/Mage/src/mage/target/TargetSpell.java @@ -87,6 +87,11 @@ public class TargetSpell extends TargetObject { @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + return canChoose(sourceControllerId, game); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { int count = 0; for (StackObject stackObject: game.getStack()) { if (stackObject instanceof Spell && game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match((Spell)stackObject)) { @@ -100,6 +105,11 @@ public class TargetSpell extends TargetObject { @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + return possibleTargets(sourceControllerId, game); + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); for (StackObject stackObject: game.getStack()) { if (stackObject instanceof Spell && game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match((Spell)stackObject)) { diff --git a/Mage/src/mage/target/TargetStackObject.java b/Mage/src/mage/target/TargetStackObject.java index 316d763417c..c2e416f7439 100644 --- a/Mage/src/mage/target/TargetStackObject.java +++ b/Mage/src/mage/target/TargetStackObject.java @@ -86,6 +86,11 @@ public class TargetStackObject extends TargetObject { @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + return canChoose(sourceControllerId, game); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { int count = 0; for (StackObject stackObject: game.getStack()) { if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject)) { @@ -99,6 +104,11 @@ public class TargetStackObject extends TargetObject { @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + return possibleTargets(sourceControllerId, game); + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); for (StackObject stackObject: game.getStack()) { if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject)) { diff --git a/Mage/src/mage/target/Targets.java b/Mage/src/mage/target/Targets.java index 0d60bf7f9b1..3af794c94ed 100644 --- a/Mage/src/mage/target/Targets.java +++ b/Mage/src/mage/target/Targets.java @@ -73,7 +73,7 @@ public class Targets extends ArrayList { } public boolean choose(Outcome outcome, UUID playerId, Game game) { - if (this.size() > 0) { + if (this.size() > 0 && canChoose(playerId, game)) { while (!isChosen()) { Target target = this.getUnchosen().get(0); if (!target.choose(outcome, playerId, game)) @@ -84,7 +84,7 @@ public class Targets extends ArrayList { } public boolean chooseTargets(Outcome outcome, UUID playerId, Ability source, Game game) { - if (this.size() > 0) { + if (this.size() > 0 && canChoose(source.getSourceId(), playerId, game)) { while (!isChosen()) { Target target = this.getUnchosen().get(0); if (!target.chooseTarget(outcome, playerId, source, game)) @@ -103,6 +103,15 @@ public class Targets extends ArrayList { return true; } + /** + * Checks if there are enough targets that can be chosen. Should only be used + * for Ability targets since this checks for protection, shroud etc. + * + * @param sourceId - the target event source + * @param sourceControllerId - controller of the target event source + * @param game + * @return - true if enough valid targets exist + */ public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { for (Target target: this) { if (!target.canChoose(sourceId, sourceControllerId, game)) @@ -111,6 +120,22 @@ public class Targets extends ArrayList { return true; } + /** + * Checks if there are enough objects that can be selected. Should not be used + * for Ability targets since this does not check for protection, shroud etc. + * + * @param sourceControllerId - controller of the select event + * @param game + * @return - true if enough valid objects exist + */ + public boolean canChoose(UUID sourceControllerId, Game game) { + for (Target target: this) { + if (!target.canChoose(sourceControllerId, game)) + return false; + } + return true; + } + public UUID getFirstTarget() { if (this.size() > 0) return this.get(0).getFirstTarget(); diff --git a/Mage/src/mage/target/common/TargetCreatureOrPlayer.java b/Mage/src/mage/target/common/TargetCreatureOrPlayer.java index 3e218d35e91..00fa22362d5 100644 --- a/Mage/src/mage/target/common/TargetCreatureOrPlayer.java +++ b/Mage/src/mage/target/common/TargetCreatureOrPlayer.java @@ -107,6 +107,15 @@ public class TargetCreatureOrPlayer extends TargetImpl { return false; } + /** + * Checks if there are enough {@link Permanent} or {@link Player} that can be chosen. Should only be used + * for Ability targets since this checks for protection, shroud etc. + * + * @param sourceId - the target event source + * @param sourceControllerId - controller of the target event source + * @param game + * @return - true if enough valid {@link Permanent} or {@link Player} exist + */ @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { int count = 0; @@ -129,6 +138,35 @@ public class TargetCreatureOrPlayer extends TargetImpl { return false; } + /** + * Checks if there are enough {@link Permanent} or {@link Player} that can be selected. Should not be used + * for Ability targets since this does not check for protection, shroud etc. + * + * @param sourceControllerId - controller of the select event + * @param game + * @return - true if enough valid {@link Permanent} or {@link Player} exist + */ + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + int count = 0; + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && filter.match(player)) { + count++; + if (count >= this.minNumberOfTargets) + return true; + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(FilterCreaturePermanent.getDefault(), sourceControllerId, game)) { + if (filter.match(permanent, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) + return true; + } + } + return false; + } + @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); @@ -147,6 +185,23 @@ public class TargetCreatureOrPlayer extends TargetImpl { return possibleTargets; } + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet(); + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && filter.match(player)) { + possibleTargets.add(playerId); + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(FilterCreaturePermanent.getDefault(), sourceControllerId, game)) { + if (filter.match(permanent, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + @Override public String getTargetedName(Game game) { StringBuilder sb = new StringBuilder(); diff --git a/Mage/src/mage/target/common/TargetCreatureOrPlayerAmount.java b/Mage/src/mage/target/common/TargetCreatureOrPlayerAmount.java index 507fb70c561..af932aecbcd 100644 --- a/Mage/src/mage/target/common/TargetCreatureOrPlayerAmount.java +++ b/Mage/src/mage/target/common/TargetCreatureOrPlayerAmount.java @@ -120,6 +120,27 @@ public class TargetCreatureOrPlayerAmount extends TargetAmount= this.minNumberOfTargets) + return true; + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(FilterCreaturePermanent.getDefault(), sourceControllerId, game)) { + if (filter.match(permanent, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) + return true; + } + } + return false; + } + @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); @@ -138,6 +159,23 @@ public class TargetCreatureOrPlayerAmount extends TargetAmount possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet(); + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && filter.match(player)) { + possibleTargets.add(playerId); + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(FilterCreaturePermanent.getDefault(), sourceControllerId, game)) { + if (filter.match(permanent, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + @Override public String getTargetedName(Game game) { StringBuilder sb = new StringBuilder(); diff --git a/Mage/src/mage/target/common/TargetDefender.java b/Mage/src/mage/target/common/TargetDefender.java index fbf43277e1b..0c43a815998 100644 --- a/Mage/src/mage/target/common/TargetDefender.java +++ b/Mage/src/mage/target/common/TargetDefender.java @@ -101,6 +101,27 @@ public class TargetDefender extends TargetImpl { return false; } + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + int count = 0; + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && filter.match(player)) { + count++; + if (count >= this.minNumberOfTargets) + return true; + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterPlaneswalkerPermanent(), sourceControllerId, game)) { + if (filter.match(permanent)) { + count++; + if (count >= this.minNumberOfTargets) + return true; + } + } + return false; + } + @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet(); @@ -119,6 +140,23 @@ public class TargetDefender extends TargetImpl { return possibleTargets; } + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet(); + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && filter.match(player)) { + possibleTargets.add(playerId); + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterPlaneswalkerPermanent(), sourceControllerId, game)) { + if (filter.match(permanent)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + @Override public String getTargetedName(Game game) { StringBuilder sb = new StringBuilder();