diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java index d4f4632395..aad84f3839 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java @@ -71,6 +71,32 @@ public class AusHighlander extends Constructed { valid = false; } + banned.add("Advantageous Proclamation"); + banned.add("Amulet of Quoz"); + banned.add("Backup Plan"); + banned.add("Brago's Favor"); + banned.add("Bronze Tablet"); + banned.add("Chaos Orb"); + banned.add("Contract from Below"); + banned.add("Darkpact"); + banned.add("Demonic Attorney"); + banned.add("Double Stroke"); + banned.add("Falling Star"); + banned.add("Immediate Action"); + banned.add("Iterative Analysis"); + banned.add("Jeweled Bird"); + banned.add("Muzzio's Preparations"); + banned.add("Power Play"); + banned.add("Rebirth"); + banned.add("Secret Summoning"); + banned.add("Secrets of Paradise"); + banned.add("Sentinel Dispatch"); + banned.add("Shahrazad"); + banned.add("Tempest Efreet"); + banned.add("Timmerian Fiends"); + banned.add("Unexpected Potential"); + banned.add("Worldknit"); + List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes", "Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); Map counts = new HashMap<>(); @@ -89,14 +115,13 @@ public class AusHighlander extends Constructed { for (Map.Entry entry : counts.entrySet()) { String cn = entry.getKey(); - if (cn.equals("Balance") + if (cn.equals("Back to Basics") + || cn.equals("Balance") || cn.equals("Birthing Pod") || cn.equals("Crop Rotation") || cn.equals("Dark Petition") - || cn.equals("Dig Through Time") || cn.equals("Enlightened Tutor") || cn.equals("Fastbond") - || cn.equals("Flash") || cn.equals("Force of Will") || cn.equals("Gifts Ungiven") || cn.equals("Green Sun's Zenith") @@ -109,12 +134,11 @@ public class AusHighlander extends Constructed { || cn.equals("Mana Vault") || cn.equals("Memory Jar") || cn.equals("Merchant Scroll") + || cn.equals("Mind Twist") || cn.equals("Mishra's Workshop") - || cn.equals("Muddle the Mixture") || cn.equals("Natural Order") || cn.equals("Oath of Druids") || cn.equals("Personal Tutor") - || cn.equals("Protean Hulk") || cn.equals("Snapcaster Mage") || cn.equals("Steelshaper's Gift") || cn.equals("Stoneforge Mystic") @@ -134,15 +158,16 @@ public class AusHighlander extends Constructed { } if (cn.equals("Channel") + || cn.equals("Dig Through Time") || cn.equals("Library of Alexandria") || cn.equals("Mana Crypt") - || cn.equals("Mind Twist") || cn.equals("Mox Emerald") || cn.equals("Mox Jet") || cn.equals("Mox Pearl") || cn.equals("Mox Ruby") || cn.equals("Mox Sapphire") || cn.equals("Mystical Tutor") + || cn.equals("Protean Hulk") || cn.equals("Skullclamp") || cn.equals("Strip Mine") || cn.equals("Tolarian Academy")) { @@ -153,7 +178,6 @@ public class AusHighlander extends Constructed { if (cn.equals("Demonic Tutor") || cn.equals("Imperial Seal") || cn.equals("Sol Ring") - || cn.equals("Time Vault") || cn.equals("Time Walk") || cn.equals("Tinker") || cn.equals("Vampiric Tutor") @@ -163,7 +187,8 @@ public class AusHighlander extends Constructed { } if (cn.equals("Ancestral Recall") - || cn.equals("Black Lotus")) { + || cn.equals("Black Lotus") + || cn.equals("Time Vault")) { totalPoints += 4; invalid.put(cn, "4 points"); } diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java index 64372f5636..25123848c5 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java @@ -93,11 +93,11 @@ public class CanadianHighlander extends Constructed { if (cn.equals("Balance") || cn.equals("Dig Through Time") || cn.equals("Fastbond") - || cn.equals("Gifts Ungiven") || cn.equals("Intuition") || cn.equals("Library of Alexandria") || cn.equals("Lim-Dul's Vault") || cn.equals("Mana Vault") + || cn.equals("Merchant Scroll") || cn.equals("Mind Twist") || cn.equals("Oath of Druids") || cn.equals("Personal Tutor") @@ -106,12 +106,14 @@ public class CanadianHighlander extends Constructed { || cn.equals("Tolarian Academy") || cn.equals("Transmute Artifact") || cn.equals("Treasure Cruise") - || cn.equals("True-Name Nemesis")) { - totalPoints += 1; - invalid.put(entry.getKey(), " 1 point " + cn); + || cn.equals("True-Name Nemesis") + || cn.equals("Worldly Tutor")) { + totalPoints += 1; + invalid.put(entry.getKey(), " 1 point " + cn); } if (cn.equals("Doomsday") || cn.equals("Enlightened Tutor") + || cn.equals("Gifts Ungiven") || cn.equals("Imperial Seal") || cn.equals("Mana Crypt") || cn.equals("Mystical Tutor") @@ -119,8 +121,8 @@ public class CanadianHighlander extends Constructed { || cn.equals("Summoner's Pact") || cn.equals("Survival of the Fittest") || cn.equals("Umezawa's Jitte")) { - totalPoints += 2; - invalid.put(entry.getKey(), " 2 points " + cn); + totalPoints += 2; + invalid.put(entry.getKey(), " 2 points " + cn); } if (cn.equals("Birthing Pod") || cn.equals("Mox Emerald") @@ -130,30 +132,27 @@ public class CanadianHighlander extends Constructed { || cn.equals("Mox Sapphire") || cn.equals("Protean Hulk") || cn.equals("Vampiric Tutor")) { - totalPoints += 3; - invalid.put(entry.getKey(), " 3 points " + cn); + totalPoints += 3; + invalid.put(entry.getKey(), " 3 points " + cn); } if (cn.equals("Demonic Tutor") || cn.equals("Hermit Druid") || cn.equals("Sol Ring")) { - totalPoints += 4; - invalid.put(entry.getKey(), " 4 points " + cn); + totalPoints += 4; + invalid.put(entry.getKey(), " 4 points " + cn); } if (cn.equals("Ancestral Recall") || cn.equals("Natural Order") || cn.equals("Time Walk") || cn.equals("Tinker")) { - totalPoints += 5; - invalid.put(entry.getKey(), " 5 points " + cn); - } - if (cn.equals("Flash")) { - totalPoints += 6; - invalid.put(entry.getKey(), " 6 points " + cn); + totalPoints += 5; + invalid.put(entry.getKey(), " 5 points " + cn); } if (cn.equals("Black Lotus") + || cn.equals("Flash") || cn.equals("Time Vault")) { - totalPoints += 7; - invalid.put(entry.getKey(), " 7 points " + cn); + totalPoints += 7; + invalid.put(entry.getKey(), " 7 points " + cn); } } if (totalPoints > allowedPoints) { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java index facc01acea..22bfbe3028 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java @@ -58,7 +58,7 @@ public class DuelCommander extends Commander { banned.add("Mana Drain"); banned.add("Mana Vault"); banned.add("Mind Twist"); - banned.add("Mishra’s Workshop"); + banned.add("Mishra's Workshop"); banned.add("Mox Diamond"); banned.add("Mox Emerald"); banned.add("Mox Jet"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java index 52c7a29245..c88500dbc3 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java @@ -86,14 +86,14 @@ public class Vintage extends Constructed { restricted.add("Gush"); restricted.add("Imperial Seal"); restricted.add("Library of Alexandria"); - restricted.add("Lion’s Eye Diamond"); + restricted.add("Lion's Eye Diamond"); restricted.add("Lodestone Golem"); restricted.add("Lotus Petal"); restricted.add("Mana Crypt"); restricted.add("Mana Vault"); restricted.add("Memory Jar"); restricted.add("Merchant Scroll"); - restricted.add("Mind’s Desire"); + restricted.add("Mind's Desire"); restricted.add("Mox Emerald"); restricted.add("Mox Jet"); restricted.add("Mox Pearl"); @@ -114,8 +114,8 @@ public class Vintage extends Constructed { restricted.add("Vampiric Tutor"); restricted.add("Wheel of Fortune"); restricted.add("Windfall"); - restricted.add("Yawgmoth’s Bargain"); - restricted.add("Yawgmoth’s Will"); + restricted.add("Yawgmoth's Bargain"); + restricted.add("Yawgmoth's Will"); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java index 674e733ad5..88d23b08ee 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java @@ -1,5 +1,6 @@ package org.mage.test.cards.cost.alternate; +import mage.abilities.keyword.DoubleStrikeAbility; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Ignore; @@ -325,7 +326,52 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase { assertHandCount(playerA, 3); assertLife(playerA, 20); assertLife(playerB, 20); - } - + + @Test + public void testJelevaCastingSavageBeatingFromExile() { + + /* + Jeleva, Nephalia's Scourge {1}{U}{B}{R} + Legendary Creature - Vampire Wizard 1/3 + Flying + When Jeleva, Nephalia's Scourge enters the battlefield, each player exiles the top X cards of his or her library, where X is the amount of mana spent to cast Jeleva. + Whenever Jeleva attacks, you may cast an instant or sorcery card exiled with it without paying its mana cost. + */ + String jeleva = "Jeleva, Nephalia's Scourge"; + + /* + Savage Beating {3}{R}{R} + Instant + Cast Savage Beating only during your turn and only during combat. + Choose one - + - Creatures you control gain double strike until end of turn. + - Untap all creatures you control. After this phase, there is an additional combat phase. + Entwine {1}{R} (Choose both if you pay the entwine cost.) + */ + String savageBeating = "Savage Beating"; + + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, savageBeating); + addCard(Zone.HAND, playerA, jeleva); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, jeleva); + + attack(3, playerA, jeleva); + setChoice(playerA, "Yes"); // opt to use Jeleva ability + setChoice(playerA, savageBeating); // choose to cast Savage Beating for free + setChoice(playerA, "No"); // opt not to pay entwine cost + setModeChoice(playerA, "1"); // use first mode of Savage Beating granting double strike + + setStopAt(3, PhaseStep.END_COMBAT); + execute(); + + assertTapped(jeleva, true); + assertLife(playerB, 18); + assertAbility(playerA, jeleva, DoubleStrikeAbility.getInstance(), true); + assertGraveyardCount(playerA, savageBeating, 1); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java new file mode 100644 index 0000000000..2354b76a18 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java @@ -0,0 +1,51 @@ +package org.mage.test.cards.single.akh; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author escplan9 + */ +public class DecimatorBeetleTest extends CardTestPlayerBase { + + /* +Decimator Beetle {3}{B}{G} +Creature - Insect 4/5 +When Decimator Beetle enters the battlefield, put a -1/-1 counter on target creature you control. +Whenever Decimator Beetle attacks, remove a -1/-1 counter from target creature you control and put a -1/-1 counter on up to one target creature defending player controls. + */ + private final String decimator = "Decimator Beetle"; + + @Test + public void targetOpponentCreatureWithDecimator() { + + String grizzly = "Grizzly Bears"; // {1}{G} 2/2 + String hillGiant = "Hill Giant"; // {3}{R} 3/3 + + addCard(Zone.HAND, playerA, decimator); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerA, grizzly); + addCard(Zone.BATTLEFIELD, playerB, hillGiant); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, decimator); + addTarget(playerA, grizzly); + + attack(3, playerA, decimator); + addTarget(playerA, grizzly); + addTarget(playerA, hillGiant); + + setStopAt(3, PhaseStep.END_COMBAT); + execute(); + + assertPowerToughness(playerA, grizzly, 2, 2); // had -1/-1 counter, but removed on attack + assertPowerToughness(playerB, hillGiant, 2, 2); // gets -1/-1 counter from decimator attack ability + assertCounterCount(playerA, grizzly, CounterType.M1M1, 0); + assertCounterCount(playerB, hillGiant, CounterType.M1M1, 1); + assertLife(playerB, 16); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/LambholtPacifistTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/LambholtPacifistTest.java new file mode 100644 index 0000000000..c6c1cf23b4 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/LambholtPacifistTest.java @@ -0,0 +1,52 @@ +package org.mage.test.cards.single.soi; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author escplan9 + */ +public class LambholtPacifistTest extends CardTestPlayerBase { + + /* + Lambholt Pacifist {1}{G} + Creature - Human Shaman Werewolf 3/3 + Lambholt Pacifist can't attack unless you control a creature with power 4 or greater. + At the beginning of each upkeep, if no spells were cast last turn, transform Lambholt Pacifist. + */ + private final String lambholt = "Lambholt Pacifist"; + + @Test + public void uncrewedVehicle_LambholtCannotAttack() { + + /* + Heart of Kiran {2} + Legendary Artifact - Vehicle + Flying, vigilance + Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.) + You may remove a loyalty counter from a planeswalker you control rather than pay Heart of Kiran's crew cost. + */ + String heartKiran = "Heart of Kiran"; + String orni = "Ornithopter"; // {0} 0/2 flyer - just needs something to cast to prevent lambholt transforming + + addCard(Zone.HAND, playerA, lambholt); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerA, heartKiran); + addCard(Zone.HAND, playerB, orni); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lambholt); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, orni); + + attack(3, playerA, lambholt); + + setStopAt(3, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerB, orni, 1); + assertTapped(lambholt, false); + assertLife(playerB, 20); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/combat/AttackBlockRestrictionsTest.java b/Mage.Tests/src/test/java/org/mage/test/combat/AttackBlockRestrictionsTest.java index 1fd7e8dc04..304530946b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/combat/AttackBlockRestrictionsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/combat/AttackBlockRestrictionsTest.java @@ -5,11 +5,10 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.game.permanent.Permanent; import org.junit.Assert; -import org.junit.Test; -import org.mage.test.serverside.base.CardTestPlayerBase; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; /** * Test restrictions for choosing attackers and blockers. @@ -543,7 +542,4 @@ public class AttackBlockRestrictionsTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20); } - - - }