diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index be03f87bb2..1060b43dc4 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -396,16 +396,18 @@ public class ComputerPlayer> extends PlayerImpl i targets = threats(opponentId, source.getSourceId(), ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game, target.getTargets()); } - if (outcome.isGood()) { - if (target.canTarget(playerId, source, game)) { - target.addTarget(playerId, source, game); - return true; + if (targets.isEmpty()) { + if (outcome.isGood()) { + if (target.canTarget(playerId, source, game)) { + target.addTarget(playerId, source, game); + return true; + } } - } - else { - if (target.canTarget(opponentId, source, game)) { - target.addTarget(opponentId, source, game); - return true; + else { + if (target.canTarget(opponentId, source, game)) { + target.addTarget(opponentId, source, game); + return true; + } } } @@ -422,6 +424,19 @@ public class ComputerPlayer> extends PlayerImpl i } } + if (outcome.isGood()) { + if (target.canTarget(playerId, source, game)) { + target.addTarget(playerId, source, game); + return true; + } + } + else { + if (target.canTarget(opponentId, source, game)) { + target.addTarget(opponentId, source, game); + return true; + } + } + if (!target.isRequired()) return false; } @@ -1501,12 +1516,12 @@ public class ComputerPlayer> extends PlayerImpl i protected List threats(UUID playerId, UUID sourceId, FilterPermanent filter, Game game, List targets) { List threats = playerId == null ? game.getBattlefield().getAllActivePermanents(filter) : - game.getBattlefield().getAllActivePermanents(filter, playerId); + game.getBattlefield().getActivePermanents(filter, playerId, sourceId, game); Iterator it = threats.iterator(); while (it.hasNext()) { // remove permanents already targeted Permanent test = it.next(); - if (targets.contains(test.getId())) + if (targets.contains(test.getId()) || (playerId != null && !test.getControllerId().equals(playerId))) it.remove(); } Collections.sort(threats, new PermanentComparator(game)); diff --git a/Mage.Tests/RB Aggro.dck b/Mage.Tests/RB Aggro.dck index 604fc32923..fc6cc06bba 100644 --- a/Mage.Tests/RB Aggro.dck +++ b/Mage.Tests/RB Aggro.dck @@ -1,19 +1,72 @@ -NAME:RB Aggro -4 [ALA:156] Blightning -2 [ZEN:245] Mountain -2 [ZEN:244] Mountain -2 [ZEN:243] Mountain -2 [ZEN:242] Mountain -4 [ZEN:223] Scalding Tarn -4 [M10:146] Lightning Bolt -4 [WWK:139] Lavaclaw Reaches -3 [M10:134] Earthquake -4 [ZEN:126] Goblin Guide -4 [CON:65] Hellspark Elemental -4 [M10:125] Ball Lightning -4 [ALA:103] Hell's Thunder -2 [CON:70] Quenchable Fire -3 [ZEN:119] Burst Lightning -4 [ZEN:211] Arid Mesa -4 [M10:223] Dragonskull Summit -4 [WWK:90] Searing Blaze +NAME:RB Aggro +1 [GUR:3] Mountain +1 [SHM:296] Mountain +1 [AVR:240] Mountain +1 [SHM:295] Mountain +1 [SHM:294] Mountain +1 [TSP:295] Mountain +1 [TSP:294] Mountain +1 [10E:379] Mountain +1 [SOM:245] Mountain +1 [ZEN:262] Mountain +1 [ZEN:245] Mountain +1 [10E:378] Mountain +1 [SOM:244] Mountain +1 [SOM:243] Mountain +1 [ZEN:244] Mountain +1 [SOM:242] Mountain +1 [ZEN:243] Mountain +1 [ZEN:242] Mountain +1 [ALA:243] Mountain +1 [ALA:242] Mountain +1 [M12:245] Mountain +1 [CHK:299] Mountain +1 [M12:243] Mountain +1 [M12:244] Mountain +1 [CHK:300] Mountain +1 [CHK:301] Mountain +1 [M12:242] Mountain +1 [CHK:302] Mountain +1 [10E:376] Mountain +1 [M11:243] Mountain +1 [M11:242] Mountain +1 [M11:245] Mountain +1 [M11:244] Mountain +1 [MBS:152] Mountain +1 [ALA:244] Mountain +1 [ALA:245] Mountain +1 [ZEN:263] Mountain +1 [ZEN:264] Mountain +1 [RAV:301] Mountain +1 [RAV:300] Mountain +1 [RAV:299] Mountain +1 [USG:345] Mountain +1 [USG:346] Mountain +1 [M10:242] Mountain +1 [RAV:302] Mountain +1 [USG:343] Mountain +1 [USG:344] Mountain +1 [ISD:259] Mountain +1 [ROE:244] Mountain +1 [ISD:261] Mountain +1 [ISD:260] Mountain +1 [ROE:241] Mountain +1 [ROE:242] Mountain +1 [ROE:243] Mountain +1 [MRD:301] Mountain +1 [MRD:300] Mountain +1 [MRD:299] Mountain +1 [M10:244] Mountain +1 [M10:243] Mountain +1 [M10:245] Mountain +1 [LRW:294] Mountain +1 [TMP:319] Mountain +1 [LRW:295] Mountain +1 [LRW:296] Mountain +1 [LRW:297] Mountain +1 [TMP:322] Mountain +1 [MRD:302] Mountain +1 [TMP:320] Mountain +1 [TMP:321] Mountain +1 [INV:345] Mountain +1 [INV:344] Mountain diff --git a/Mage.Tests/plugins/mage-player-ai.jar b/Mage.Tests/plugins/mage-player-ai.jar index 75a2856149..765ddf699e 100644 Binary files a/Mage.Tests/plugins/mage-player-ai.jar and b/Mage.Tests/plugins/mage-player-ai.jar differ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java index b1112ddf85..e1a668f951 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java @@ -350,6 +350,7 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { assertAbilities(playerA, "Elite Vanguard", abilities); } + @Test public void testExileAndReturnBack() { //TODO: Soulbond + Soulshift Assert.assertTrue(false); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/ArchangelsLightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/ArchangelsLightTest.java index 4c53a17287..a8736273e3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/ArchangelsLightTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/ArchangelsLightTest.java @@ -26,7 +26,7 @@ public class ArchangelsLightTest extends CardTestPlayerBase { assertLife(playerB, 20); assertGraveyardCount(playerA, 1); assertGraveyardCount(playerA, "Archangel's Light", 1); - Assert.assertEquals(currentGame.getPlayer(playerA.getId()).getLibrary().size(), 66); + Assert.assertEquals(currentGame.getPlayer(playerA.getId()).getLibrary().size(), 77); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/SorinLordOfInnistradTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/SorinLordOfInnistradTest.java index 83f1b8bd02..6f0ca76cc3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/SorinLordOfInnistradTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/SorinLordOfInnistradTest.java @@ -61,10 +61,10 @@ public class SorinLordOfInnistradTest extends CardTestPlayerBase { assertLife(playerA, 23); assertLife(playerB, 20); assertPermanentCount(playerA, "Sorin, Lord of Innistrad", 0); - assertPermanentCount(playerA, "Craw Wurm", 1); assertPermanentCount(playerB, "Craw Wurm", 0); - assertPermanentCount(playerA, "Angel of Mercy", 1); assertPermanentCount(playerB, "Angel of Mercy", 0); + assertPermanentCount(playerA, "Craw Wurm", 1); + assertPermanentCount(playerA, "Angel of Mercy", 1); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/targets/attacking/CondemnTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/targets/attacking/CondemnTest.java index e6639a8159..64d5593030 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/targets/attacking/CondemnTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/targets/attacking/CondemnTest.java @@ -42,8 +42,9 @@ public class CondemnTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Sejiri Merfolk", 0); assertLife(playerB, 20); assertLife(playerA, 21); + // check was put on top - Assert.assertEquals(currentGame.getPlayer(playerA.getId()).getLibrary().size(), 61); + Assert.assertEquals(72, currentGame.getPlayer(playerA.getId()).getLibrary().size()); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BloodArtistTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BloodArtistTest.java index 93bc02c139..23bcf4605b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BloodArtistTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BloodArtistTest.java @@ -13,7 +13,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class BloodArtistTest extends CardTestPlayerBase { /** - * Tests that whenever Blood Artist goes to graveyard, it would trigget its ability. + * Tests that whenever Blood Artist goes to graveyard, it would trigger its ability. * Tests that after Blood Artist went to graveyard, his ability doesn't work anymore. */ @Test @@ -26,9 +26,9 @@ public class BloodArtistTest extends CardTestPlayerBase { addCard(Constants.Zone.BATTLEFIELD, playerB, "Bloodflow Connoisseur", 1); castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Blood Artist"); - castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Bloodflow Connoisseur"); + castSpell(1, Constants.PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Bloodflow Connoisseur"); - setStopAt(1, Constants.PhaseStep.BEGIN_COMBAT); + setStopAt(1, Constants.PhaseStep.END_TURN); execute(); assertLife(playerA, 23); diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 415bf3afef..b65d434543 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -230,7 +230,9 @@ public class TestPlayer extends ComputerPlayer { for (UUID id: ability.getTargets().get(0).possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) { MageObject object = game.getObject(id); if (object != null && object.getName().equals(t)) { - ability.getTargets().get(0).clearChosen(); + if (ability.getTargets().get(0).getNumberOfTargets() == 1) { + ability.getTargets().get(0).clearChosen(); + } ability.getTargets().get(0).addTarget(id, ability, game); break; } diff --git a/Mage/src/mage/abilities/Ability.java b/Mage/src/mage/abilities/Ability.java index 6114267fc2..b50a6acadb 100644 --- a/Mage/src/mage/abilities/Ability.java +++ b/Mage/src/mage/abilities/Ability.java @@ -28,9 +28,6 @@ package mage.abilities; -import java.io.Serializable; -import java.util.List; -import java.util.UUID; import mage.Constants.AbilityType; import mage.Constants.EffectType; import mage.Constants.Zone; @@ -47,6 +44,10 @@ import mage.game.Game; import mage.target.Target; import mage.target.Targets; +import java.io.Serializable; +import java.util.List; +import java.util.UUID; + /** * Practically everything in the game is started from an Ability. This * interface describes what an Ability is composed of at the highest level. @@ -356,8 +357,9 @@ public interface Ability extends Serializable { * Returns true if this abilities source is in the zone for the ability * * @param game + * @param checkLKI * @return */ - public boolean isInUseableZone(Game game); + public boolean isInUseableZone(Game game, boolean checkLKI); } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index fc33a0df35..9674789650 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -458,12 +458,14 @@ public abstract class AbilityImpl> implements Ability { } @Override - public boolean isInUseableZone(Game game) { + public boolean isInUseableZone(Game game, boolean checkLKI) { // try LKI first - MageObject lkiTest = game.getLastKnownInformation(getSourceId(), zone); - if (lkiTest != null) { - return true; + if (checkLKI) { + MageObject lkiTest = game.getLastKnownInformation(getSourceId(), zone); + if (lkiTest != null) { + return true; + } } // check against current state diff --git a/Mage/src/mage/abilities/TriggeredAbilities.java b/Mage/src/mage/abilities/TriggeredAbilities.java index a751284666..94360f8235 100644 --- a/Mage/src/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/mage/abilities/TriggeredAbilities.java @@ -28,13 +28,14 @@ package mage.abilities; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.MageObject; import mage.game.Game; import mage.game.events.GameEvent; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** * * @author BetaSteward_at_googlemail.com @@ -51,7 +52,7 @@ public class TriggeredAbilities extends HashMap { public void checkTriggers(GameEvent event, Game game) { for (TriggeredAbility ability: this.values()) { - if (ability.isInUseableZone(game)) { + if (ability.isInUseableZone(game, true)) { MageObject object = game.getLastKnownInformation(ability.getSourceId(), event.getZone()); if (object == null) { object = game.getObject(ability.getSourceId()); diff --git a/Mage/src/mage/abilities/common/DiesTriggeredAbility.java b/Mage/src/mage/abilities/common/DiesTriggeredAbility.java index b0798164e6..30e742ca58 100644 --- a/Mage/src/mage/abilities/common/DiesTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DiesTriggeredAbility.java @@ -28,15 +28,11 @@ package mage.abilities.common; -import java.util.UUID; - import mage.Constants; import mage.Constants.Zone; import mage.MageObject; import mage.abilities.effects.Effect; -import mage.cards.Card; import mage.game.Game; -import mage.game.events.GameEvent; /** * @@ -59,7 +55,7 @@ public class DiesTriggeredAbility extends ZoneChangeTriggeredAbility effects = new ArrayList(); for (RequirementEffect effect: requirementEffects) { Ability ability = requirementEffects.getAbility(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, false)) { if (effect.applies(permanent, ability, game)) effects.add(effect); } @@ -175,7 +175,7 @@ public class ContinuousEffects implements Serializable { List effects = new ArrayList(); for (RestrictionEffect effect: restrictionEffects) { Ability ability = restrictionEffects.getAbility(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, false)) { if (effect.applies(permanent, ability, game)) effects.add(effect); } @@ -198,7 +198,7 @@ public class ContinuousEffects implements Serializable { //get all applicable transient Replacement effects for (ReplacementEffect effect: replacementEffects) { Ability ability = replacementEffects.getAbility(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, false)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.applies(event, ability, game)) { replaceEffects.add(effect); @@ -208,7 +208,7 @@ public class ContinuousEffects implements Serializable { } for (PreventionEffect effect: preventionEffects) { Ability ability = preventionEffects.getAbility(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, false)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.applies(event, ability, game)) { replaceEffects.add(effect); @@ -230,7 +230,7 @@ public class ContinuousEffects implements Serializable { for (CostModificationEffect effect: costModificationEffects) { Ability ability = costModificationEffects.getAbility(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, false)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { costEffects.add(effect); } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 88b3a072d3..dd3869c905 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -640,7 +640,7 @@ public abstract class GameImpl> implements Game, Serializa if (checkStateAndTriggered()) { applyEffects(); } - resetLKI(); + //resetLKI(); applyEffects(); if (isPaused() || isGameOver()) return; // resetPassed should be called if player performs any action @@ -660,7 +660,7 @@ public abstract class GameImpl> implements Game, Serializa state.getPlayers().resetPassed(); fireUpdatePlayersEvent(); state.getRevealed().reset(); - resetLKI(); + //resetLKI(); break; } else { //removeBookmark(bookmark); diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index a3e18526e5..00a7e48e03 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -28,16 +28,6 @@ package mage.game; -import mage.abilities.TriggeredAbility; -import mage.game.events.GameEvent; -import mage.game.stack.SpellStack; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; import mage.Constants.Zone; import mage.abilities.*; import mage.abilities.effects.ContinuousEffect; @@ -48,11 +38,10 @@ import mage.choices.Choice; import mage.game.combat.Combat; import mage.game.combat.CombatGroup; import mage.game.command.Command; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; +import mage.game.events.GameEvent; import mage.game.permanent.Battlefield; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; +import mage.game.stack.SpellStack; import mage.game.stack.StackObject; import mage.game.turn.Turn; import mage.game.turn.TurnMods; @@ -64,6 +53,9 @@ import mage.util.Copyable; import mage.watchers.Watcher; import mage.watchers.Watchers; +import java.io.Serializable; +import java.util.*; + /** * * @author BetaSteward_at_googlemail.com diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index 7125fd45b2..94cd3e9fc9 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -28,37 +28,32 @@ package mage.game.stack; -import java.util.ArrayList; import mage.Constants.AbilityType; -import mage.abilities.Mode; -import mage.abilities.Modes; -import mage.abilities.costs.AlternativeCost; -import mage.abilities.costs.Cost; -import mage.abilities.costs.Costs; -import mage.abilities.costs.mana.ManaCost; -import mage.abilities.effects.Effect; -import mage.abilities.effects.Effects; -import mage.choices.Choice; -import mage.choices.Choices; -import mage.game.*; -import java.util.List; -import java.util.UUID; import mage.Constants.CardType; import mage.Constants.EffectType; import mage.Constants.Zone; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.Abilities; -import mage.abilities.AbilitiesImpl; -import mage.abilities.Ability; -import mage.abilities.StateTriggeredAbility; +import mage.abilities.*; +import mage.abilities.costs.AlternativeCost; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.game.events.GameEvent; +import mage.abilities.effects.Effect; +import mage.abilities.effects.Effects; +import mage.choices.Choice; +import mage.choices.Choices; +import mage.game.Game; import mage.target.Target; import mage.target.Targets; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * * @author BetaSteward_at_googlemail.com @@ -329,7 +324,7 @@ public class StackAbility implements StackObject, Ability { } @Override - public boolean isInUseableZone(Game game) { + public boolean isInUseableZone(Game game, boolean checkLKI) { throw new UnsupportedOperationException("Not supported yet."); } }