diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java index ca3091211b..404f4eaa20 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java @@ -203,7 +203,9 @@ public class RateCard { maxSingleCount = Math.max(maxSingleCount, typeCount); } } - return 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]/*-DOUBLE_PENALTY[doubleCount]*/); + if (maxSingleCount > 5) + maxSingleCount = 5; + return 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]/*-DOUBLE_PENALTY[doubleCount]*/); } /** diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index cf196b3c47..2041685d8e 100644 Binary files a/Mage.Server/plugins/mage-player-ai.jar and b/Mage.Server/plugins/mage-player-ai.jar differ diff --git a/Mage.Sets/src/mage/sets/innistrad/HarvestPyre.java b/Mage.Sets/src/mage/sets/innistrad/HarvestPyre.java index 46c79c43dc..31766906db 100644 --- a/Mage.Sets/src/mage/sets/innistrad/HarvestPyre.java +++ b/Mage.Sets/src/mage/sets/innistrad/HarvestPyre.java @@ -100,7 +100,7 @@ class HarvestPyreCost extends CostImpl implements VariableCost Player player = game.getPlayer(controllerId); while (true) { target.clearChosen(); - if (target.choose(Outcome.Exile, controllerId, sourceId, game)) { + if (target.canChoose(controllerId, game) && target.choose(Outcome.Exile, controllerId, sourceId, game)) { Card card = player.getGraveyard().get(target.getFirstTarget(), game); if (card != null) { player.getGraveyard().remove(card); diff --git a/Mage.Sets/src/mage/sets/morningtide/PreeminentCaptain.java b/Mage.Sets/src/mage/sets/morningtide/PreeminentCaptain.java index a057f63a37..0d621407c0 100644 --- a/Mage.Sets/src/mage/sets/morningtide/PreeminentCaptain.java +++ b/Mage.Sets/src/mage/sets/morningtide/PreeminentCaptain.java @@ -96,7 +96,7 @@ class PreeminentCaptainEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); TargetCardInHand target = new TargetCardInHand(new FilterSoldierCard()); - if (target.choose(getOutcome(), player.getId(), source.getSourceId(), game)) { + if (target.canChoose(player.getId(), game) && target.choose(getOutcome(), player.getId(), source.getSourceId(), game)) { if (target.getTargets().size() > 0) { UUID cardId = target.getFirstTarget(); Card card = player.getHand().get(cardId, game); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/MortisDogs.java b/Mage.Sets/src/mage/sets/newphyrexia/MortisDogs.java index 3ff00ffb32..73c1415cff 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/MortisDogs.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/MortisDogs.java @@ -91,7 +91,7 @@ class MortisDogsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(source)); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (player != null) { + if (player != null && sourcePermanent != null) { player.loseLife(sourcePermanent.getPower().getValue(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/zendikar/CobraTrap.java b/Mage.Sets/src/mage/sets/zendikar/CobraTrap.java index 888cb91aad..d2964df262 100644 --- a/Mage.Sets/src/mage/sets/zendikar/CobraTrap.java +++ b/Mage.Sets/src/mage/sets/zendikar/CobraTrap.java @@ -32,16 +32,19 @@ import mage.Constants.CardType; import mage.Constants.ColoredManaSymbol; import mage.Constants.Rarity; import mage.Constants.WatcherScope; +import mage.Constants.Zone; import mage.abilities.Ability; import mage.abilities.costs.AlternativeCostImpl; import mage.abilities.costs.mana.ColoredManaCost; import mage.abilities.effects.common.CreateTokenEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; import mage.game.permanent.token.SnakeToken; +import mage.game.stack.StackObject; +import mage.players.Player; import mage.watchers.Watcher; import mage.watchers.WatcherImpl; @@ -96,11 +99,17 @@ class CobraTrapWatcher extends WatcherImpl { if (condition == true) { // no need to check - condition has already occured return; } - if (event.getType() == EventType.DESTROYED_PERMANENT - && !game.getPlayer(controllerId).getGraveyard().get(event.getTargetId(), game).getCardType().contains(CardType.CREATURE) - && game.getStack().getStackObject(event.getSourceId()) != null - && game.getOpponents(controllerId).contains(game.getStack().getStackObject(event.getSourceId()).getControllerId())) { - condition = true; + Player player = game.getPlayer(controllerId); + if (player != null && event.getType() == EventType.DESTROYED_PERMANENT) { + Permanent perm = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); + if (perm != null && !perm.getCardType().contains(CardType.CREATURE)) { + if (game.getStack().size() > 0) { + StackObject spell = game.getStack().getStackObject(event.getSourceId()); + if (spell != null && game.getOpponents(controllerId).contains(spell.getControllerId())) { + condition = true; + } + } + } } } } diff --git a/Mage.Tests/plugins/mage-player-ai.jar b/Mage.Tests/plugins/mage-player-ai.jar index 387174114d..2041685d8e 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/TestCobraTrap.java b/Mage.Tests/src/test/java/org/mage/test/cards/TestCobraTrap.java new file mode 100644 index 0000000000..20da51773e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/TestCobraTrap.java @@ -0,0 +1,50 @@ +package org.mage.test.cards; + +import mage.Constants; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author BetaSteward + */ +public class TestCobraTrap extends CardTestPlayerBase { + + @Test + public void testCard() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Constants.Zone.HAND, playerA, "Cobra Trap"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Mountain", 3); + addCard(Constants.Zone.HAND, playerB, "Stone Rain"); + + castSpell(2, Constants.PhaseStep.PRECOMBAT_MAIN, playerB, "Stone Rain", "Forest"); + castSpell(2, Constants.PhaseStep.POSTCOMBAT_MAIN, playerA, "Cobra Trap"); + + setStopAt(2, Constants.PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Forest", 1); + assertPermanentCount(playerA, "Snake", 4); + } + + @Test + public void testCardNegative() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Constants.Zone.HAND, playerA, "Cobra Trap"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Mountain", 3); + addCard(Constants.Zone.HAND, playerB, "Stone Rain"); + + castSpell(2, Constants.PhaseStep.POSTCOMBAT_MAIN, playerA, "Cobra Trap"); + + setStopAt(2, Constants.PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Forest", 2); + assertPermanentCount(playerA, "Snake", 0); + } + +} diff --git a/Mage/src/mage/abilities/keyword/BloodthirstAbility.java b/Mage/src/mage/abilities/keyword/BloodthirstAbility.java index 4a4d98ebe4..8f68caf559 100644 --- a/Mage/src/mage/abilities/keyword/BloodthirstAbility.java +++ b/Mage/src/mage/abilities/keyword/BloodthirstAbility.java @@ -58,7 +58,7 @@ class BloodthirstEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); if (player != null) { BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get("DamagedOpponents", source.getControllerId()); - if (watcher.conditionMet()) { + if (watcher != null && watcher.conditionMet()) { Permanent p = game.getPermanent(source.getSourceId()); if (p != null) { p.addCounters(CounterType.P1P1.createInstance(amount), game); diff --git a/Mage/src/mage/abilities/keyword/CascadeAbility.java b/Mage/src/mage/abilities/keyword/CascadeAbility.java index dbab9913a1..6d1aaf6602 100644 --- a/Mage/src/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/mage/abilities/keyword/CascadeAbility.java @@ -96,7 +96,7 @@ class CascadeEffect extends OneShotEffect { ExileZone exile = game.getExile().createZone(source.getSourceId(), player.getName() + " Cascade"); int sourceCost = game.getObject(source.getSourceId()).getManaCost().convertedManaCost(); do { - card = player.getLibrary().getFromTop(game); + card = player.getLibrary().removeFromTop(game); if (card == null) break; card.moveToExile(exile.getId(), exile.getName(), source.getId(), game); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 97c9f81039..ad47865f0a 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -489,7 +489,8 @@ public abstract class PlayerImpl> implements Player, Ser Ability spellAbility = game.getStack().getSpell(ability.getId()).getSpellAbility(); if (spellAbility.activate(game, noMana)) { for (KickerAbility kicker: card.getAbilities().getKickerAbilities()) { - kicker.activate(game, false); + if (kicker.getCosts().canPay(ability.getSourceId(), playerId, game) && kicker.canChooseTarget(game)) + kicker.activate(game, false); } GameEvent event = GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spellAbility.getId(), spellAbility.getSourceId(), playerId); event.setZone(fromZone); @@ -1209,7 +1210,10 @@ public abstract class PlayerImpl> implements Player, Ser } } } - + for (AlternativeCost cost: ability.getAlternativeCosts()) { + if (cost.isAvailable(game, ability) && cost.canPay(ability.getSourceId(), playerId, game)) + return true; + } } return false; } diff --git a/Mage/src/mage/target/TargetObject.java b/Mage/src/mage/target/TargetObject.java index 38a3d1e257..9e6567b782 100644 --- a/Mage/src/mage/target/TargetObject.java +++ b/Mage/src/mage/target/TargetObject.java @@ -66,7 +66,9 @@ public abstract class TargetObject> extends TargetImpl public String getTargetedName(Game game) { StringBuilder sb = new StringBuilder(); for (UUID targetId: getTargets()) { - sb.append(game.getObject(targetId).getName()).append(" "); + MageObject object = game.getObject(targetId); + if (object != null) + sb.append(object.getName()).append(" "); } return sb.toString(); }