diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java index f895228e32..b9eba1c9e1 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java @@ -111,73 +111,6 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player { calculateActions(game, nextAction); } -// @Override -// public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map options) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean chooseMulligan(Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public boolean chooseUse(Outcome outcome, String message, Game game) { -// getNextAction(game, NextAction.CHOOSE_USE); -// return root.get -// } -// -// @Override -// public boolean choose(Outcome outcome, Choice choice, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } - -// @Override -// public boolean playMana(ManaCost unpaid, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } - - -// @Override -// public int chooseEffect(List rEffects, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } -// -// @Override -// public Mode chooseMode(Modes modes, Ability source, Game game) { -// throw new UnsupportedOperationException("Not supported yet."); -// } - @Override public void selectAttackers(Game game, UUID attackingPlayerId) { StringBuilder sb = new StringBuilder(); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyEnchantmentTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyEnchantmentTest.java index 1a6c7d8a28..9e4e0fbad4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyEnchantmentTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyEnchantmentTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.copy; import mage.constants.PhaseStep; @@ -7,7 +6,6 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author LevelX2 */ public class CopyEnchantmentTest extends CardTestPlayerBase { @@ -23,18 +21,18 @@ public class CopyEnchantmentTest extends CardTestPlayerBase { // Dragon creatures you control get +3/+3. addCard(Zone.BATTLEFIELD, playerB, "Crucible of Fire", 1); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Copy Enchantment"); setChoice(playerA, "Crucible of Fire"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); assertLife(playerA, 20); assertLife(playerB, 20); - assertGraveyardCount(playerA, "Copy Enchantment",0); + assertGraveyardCount(playerA, "Copy Enchantment", 0); assertPermanentCount(playerA, "Crucible of Fire", 1); - assertPowerToughness(playerA, "Furnace Whelp", 5,5); + assertPowerToughness(playerA, "Furnace Whelp", 5, 5); } @Test @@ -52,17 +50,22 @@ public class CopyEnchantmentTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inferno Fist", "Geist of the Moors"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Copy Enchantment"); + setChoice(playerB, "Yes"); // copy + setChoice(playerB, "Inferno Fist"); // copied + setChoice(playerB, "Silvercoat Lion"); // target for copy + setStrictChooseMode(true); setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); assertLife(playerA, 20); assertLife(playerB, 20); assertHandCount(playerA, "Inferno Fist", 0); - assertGraveyardCount(playerB, "Copy Enchantment",0); + assertGraveyardCount(playerB, "Copy Enchantment", 0); assertPermanentCount(playerA, "Inferno Fist", 1); assertPermanentCount(playerB, "Inferno Fist", 1); - assertPowerToughness(playerA, "Geist of the Moors", 5,1); - assertPowerToughness(playerB, "Silvercoat Lion", 4,2); + assertPowerToughness(playerA, "Geist of the Moors", 5, 1); + assertPowerToughness(playerB, "Silvercoat Lion", 4, 2); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/RakshasaDebaserTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/RakshasaDebaserTest.java new file mode 100644 index 0000000000..341a960099 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/RakshasaDebaserTest.java @@ -0,0 +1,31 @@ +package org.mage.test.cards.single.cmr; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ + +public class RakshasaDebaserTest extends CardTestPlayerBase { + + @Test + public void test_Playable() { + // Whenever Rakshasa Debaser attacks, put target creature card from defending player's graveyard onto the battlefield under your control. + addCard(Zone.BATTLEFIELD, playerA, "Rakshasa Debaser", 1); + addCard(Zone.GRAVEYARD, playerB, "Balduvian Bears", 1); + + // attack and trigger + attack(1, playerA, "Rakshasa Debaser", playerB); + addTarget(playerA, "Balduvian Bears"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Balduvian Bears", 1); // from trigger + } +} diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index d64ca6c132..464b26424d 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -195,7 +195,7 @@ public class Modes extends LinkedHashMap { * Return real affected max modes in current game. Use null params for default max modes value. * * @param game - * @param source + * @param source can be null for rules generation * @return */ public int getMaxModes(Game game, Ability source) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java index 3cb3ed7c24..b16b59b3b8 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java @@ -1,19 +1,19 @@ package mage.filter.predicate.permanent; import mage.cards.Card; -import mage.filter.predicate.ObjectSourcePlayer; -import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.ObjectPlayer; +import mage.filter.predicate.ObjectPlayerPredicate; import mage.game.Game; /** * @author TheElk801 */ -public enum DefendingPlayerOwnsCardPredicate implements ObjectSourcePlayerPredicate> { +public enum DefendingPlayerOwnsCardPredicate implements ObjectPlayerPredicate> { instance; @Override - public boolean apply(ObjectSourcePlayer input, Game game) { - return input.getObject().isOwnedBy(game.getCombat().getDefendingPlayerId(input.getSourceId(), game)); + public boolean apply(ObjectPlayer input, Game game) { + return game.getCombat().getPlayerDefenders(game, false).contains(input.getObject().getOwnerId()); } @Override diff --git a/Mage/src/main/java/mage/target/Target.java b/Mage/src/main/java/mage/target/Target.java index 75561a0680..ae0db1ccb5 100644 --- a/Mage/src/main/java/mage/target/Target.java +++ b/Mage/src/main/java/mage/target/Target.java @@ -50,6 +50,12 @@ public interface Target extends Serializable { boolean canTarget(UUID id, Game game); + /** + * @param id + * @param source WARNING, it can be null for AI or other calls from events (TODO: introduce normal source in AI ComputerPlayer) + * @param game + * @return + */ boolean canTarget(UUID id, Ability source, Game game); boolean stillLegalTarget(UUID id, Ability source, Game game); diff --git a/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java b/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java index d256885d4f..0d1e40e512 100644 --- a/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java +++ b/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java @@ -41,6 +41,7 @@ public class TargetActivatedAbility extends TargetObject { @Override public boolean canTarget(UUID id, Ability source, Game game) { + // 114.4. A spell or ability on the stack is an illegal target for itself. if (source != null && source.getSourceId().equals(id)) { return false; } @@ -80,7 +81,7 @@ public class TargetActivatedAbility extends TargetObject { for (StackObject stackObject : game.getStack()) { if (stackObject.getStackAbility().getAbilityType() == AbilityType.ACTIVATED && game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getStackAbility().getControllerId()) - && filter.match(((StackAbility) stackObject), game)) { + && filter.match(stackObject, game)) { possibleTargets.add(stackObject.getStackAbility().getId()); } } diff --git a/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java b/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java index 5efeb3552d..1c99bc642e 100644 --- a/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java +++ b/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java @@ -1,9 +1,5 @@ - package mage.target.common; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.constants.Zone; @@ -13,8 +9,11 @@ import mage.game.Game; import mage.game.stack.StackObject; import mage.target.TargetObject; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author Styxo */ public class TargetTriggeredAbility extends TargetObject { @@ -32,6 +31,7 @@ public class TargetTriggeredAbility extends TargetObject { @Override public boolean canTarget(UUID id, Ability source, Game game) { + // 114.4. A spell or ability on the stack is an illegal target for itself. if (source != null && source.getSourceId().equals(id)) { return false; }