From c7a349f65f96052897702bf308cc46dc6c45a426 Mon Sep 17 00:00:00 2001 From: brodee Date: Tue, 14 Jul 2015 22:34:58 -0700 Subject: [PATCH 1/4] random draft bug fix: packs are forced to be 15 cards; weirdness occurs if the packs are uneven sizes including the draft ending early. Random draft ui improvements: only the sets that will be used are displayed in the lobby, and the number of characters is large but still greatly reduced. the pack selector ui will prevent you from chosing fewer than 2 packs. --- .../client/dialog/NewTournamentDialog.form | 8 ++--- .../client/dialog/NewTournamentDialog.java | 33 ++++++++++++++----- .../dialog/RandomPacksSelectorDialog.form | 4 +++ .../dialog/RandomPacksSelectorDialog.java | 21 ++++++++++-- .../server/tournament/TournamentFactory.java | 7 ++++ Mage/src/mage/cards/ExpansionSet.java | 20 +++++++++++ .../mage/game/draft/RandomBoosterDraft.java | 19 +---------- 7 files changed, 77 insertions(+), 35 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form index beb4c5799d..92ca80af08 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form @@ -169,7 +169,7 @@ - + @@ -521,10 +521,8 @@ - - - - + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 59eacfaa88..101b3f708d 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -34,8 +34,10 @@ package mage.client.dialog; +import java.awt.Component; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.UUID; import javax.swing.ComboBoxModel; @@ -122,8 +124,8 @@ public class NewTournamentDialog extends MageDialog { cbAllowSpectators.setSelected(true); setTournamentSettingsFromPrefs(); this.setModal(true); - this.setLocation(150, 100); - } + this.setLocation(150, 100); + } this.setVisible(true); } @@ -341,7 +343,7 @@ public class NewTournamentDialog extends MageDialog { pnlRandomPacks.setBorder(javax.swing.BorderFactory.createEtchedBorder()); pnlRandomPacks.setToolTipText(""); - pnlRandomPacks.setLayout(new java.awt.GridLayout(0, 1, 2, 0)); + pnlRandomPacks.setLayout(new javax.swing.BoxLayout(pnlRandomPacks, javax.swing.BoxLayout.Y_AXIS)); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); @@ -468,7 +470,7 @@ public class NewTournamentDialog extends MageDialog { .addGroup(layout.createSequentialGroup() .addComponent(pnlPacks, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlRandomPacks, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(pnlRandomPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -477,7 +479,7 @@ public class NewTournamentDialog extends MageDialog { .addComponent(lblNumRounds)) .addComponent(lblNbrPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(spnNumPlayers) - .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)) + .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lblPlayer1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -533,7 +535,18 @@ public class NewTournamentDialog extends MageDialog { tOptions.getLimitedOptions().setDraftCubeName(this.cbDraftCube.getSelectedItem().toString()); } else if (tournamentType.isRandom()) { tOptions.getLimitedOptions().getSetCodes().clear(); - tOptions.getLimitedOptions().getSetCodes().addAll(randomPackSelector.getSelectedPacks()); + ArrayList selected = randomPackSelector.getSelectedPacks(); + int maxPacks = 3 * (players.size() + 1); + if (selected.size() > maxPacks ){ + StringBuilder infoString = new StringBuilder("More sets were selected than needed. "); + infoString.append(maxPacks); + infoString.append(" sets will be randomly chosen."); + JOptionPane.showMessageDialog(MageFrame.getDesktop(), infoString, "Information", JOptionPane.INFORMATION_MESSAGE); + Collections.shuffle(selected); + tOptions.getLimitedOptions().getSetCodes().addAll(selected.subList(0, maxPacks)); + }else{ + tOptions.getLimitedOptions().getSetCodes().addAll(selected); + } } else { for (JComboBox pack: packs) { tOptions.getLimitedOptions().getSetCodes().add(((ExpansionInfo) pack.getSelectedItem()).getCode()); @@ -717,6 +730,7 @@ public class NewTournamentDialog extends MageDialog { if (pnlRandomPacks.getComponentCount() == 0) { if (randomPackSelector == null) { randomPackSelector = new RandomPacksSelectorDialog(); + randomPackSelector.setLocationRelativeTo(this); } txtRandomPacks = new JTextArea(); txtRandomPacks.setEnabled(false); @@ -736,9 +750,10 @@ public class NewTournamentDialog extends MageDialog { } txtRandomPacks.setText(packList.toString()); } - + txtRandomPacks.setAlignmentX(Component.LEFT_ALIGNMENT); pnlRandomPacks.add(txtRandomPacks); JButton btnSelectRandomPacks = new JButton(); + btnSelectRandomPacks.setAlignmentX(Component.LEFT_ALIGNMENT); btnSelectRandomPacks.setText("Select packs to be included in the pool"); btnSelectRandomPacks.setToolTipText(RandomPacksSelectorDialog.randomDraftDescription); btnSelectRandomPacks.addActionListener(new java.awt.event.ActionListener() { @@ -749,11 +764,11 @@ public class NewTournamentDialog extends MageDialog { } }); pnlRandomPacks.add(btnSelectRandomPacks); - } + } this.pack(); this.revalidate(); this.repaint(); - } + } private void showRandomPackSelectorDialog() { randomPackSelector.showDialog(); diff --git a/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.form b/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.form index d486cab047..7644055a2a 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.form @@ -2,6 +2,7 @@
+ @@ -16,6 +17,9 @@ + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.java b/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.java index 5b9b3cc0d0..083f9a42dd 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/RandomPacksSelectorDialog.java @@ -8,6 +8,7 @@ package mage.client.dialog; import java.awt.Component; import java.util.ArrayList; import javax.swing.JCheckBox; +import javax.swing.JOptionPane; import mage.cards.repository.ExpansionInfo; import mage.cards.repository.ExpansionRepository; @@ -101,11 +102,17 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog { pnlApply = new javax.swing.JPanel(); btnApply = new javax.swing.JButton(); + setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); setTitle("Random Booster Draft Packs Selector"); setModal(true); setModalExclusionType(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE); setPreferredSize(new java.awt.Dimension(600, 450)); setResizable(false); + addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosing(java.awt.event.WindowEvent evt) { + formWindowClosing(evt); + } + }); pnlPacks.setLayout(new java.awt.GridLayout(11, 12)); @@ -174,13 +181,21 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog { }//GEN-LAST:event_btnNoneActionPerformed private void btnApplyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnApplyActionPerformed + this.doApply(); + }//GEN-LAST:event_btnApplyActionPerformed + + private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing + this.doApply(); + }//GEN-LAST:event_formWindowClosing + + public void doApply() { if (getSelectedPacks().size() < 2) { - // at least 2 packs must be selected. + JOptionPane.showMessageDialog(this, "At least 2 sets must be selected", "Error", JOptionPane.ERROR_MESSAGE); } else { this.setVisible(false); } - }//GEN-LAST:event_btnApplyActionPerformed - + } + private void setAllCheckBoxes(boolean value) { for (Component pack : pnlPacks.getComponents()) { JCheckBox thePack = (JCheckBox) pack; diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java index 114331fb78..9575acc3bb 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java @@ -80,6 +80,13 @@ public class TournamentFactory { if (tournament.getTournamentType().isCubeBooster()) { tournament.getOptions().getLimitedOptions().setDraftCube(CubeFactory.getInstance().createDraftCube(tournament.getOptions().getLimitedOptions().getDraftCubeName())); tournament.setBoosterInfo(tournament.getOptions().getLimitedOptions().getDraftCubeName()); + } else if (tournament.getTournamentType().isRandom()) { + StringBuilder rv = new StringBuilder( "Random Draft using sets: "); + for (Map.Entry entry: setInfo.entrySet()){ + rv.append(entry.getKey()); + rv.append(";"); + } + tournament.setBoosterInfo(rv.toString()); } else { StringBuilder sb = new StringBuilder(); for (Map.Entry entry:setInfo.entrySet()) { diff --git a/Mage/src/mage/cards/ExpansionSet.java b/Mage/src/mage/cards/ExpansionSet.java index 5a808a456c..17aee8cbb9 100644 --- a/Mage/src/mage/cards/ExpansionSet.java +++ b/Mage/src/mage/cards/ExpansionSet.java @@ -112,6 +112,26 @@ public abstract class ExpansionSet implements Serializable { return name; } + public List create15CardBooster() { + // Forces 15 card booster packs. + // if the packs are too small, it adds commons to fill it out. + // if the packs are too big, it removes the first cards. + // since it adds lands then commons before uncommons + // and rares this should be the least disruptive. + + List theBooster = this.createBooster(); + List commons = getCardsByRarity(Rarity.COMMON); + while (15 > theBooster.size()) { + addToBooster(theBooster, commons); + } + + while (theBooster.size() > 15) { + theBooster.remove(0); + } + + return theBooster; + } + public List createBooster() { List booster = new ArrayList<>(); if (!hasBoosters) { diff --git a/Mage/src/mage/game/draft/RandomBoosterDraft.java b/Mage/src/mage/game/draft/RandomBoosterDraft.java index ebd0a8a9ef..cc7604b447 100644 --- a/Mage/src/mage/game/draft/RandomBoosterDraft.java +++ b/Mage/src/mage/game/draft/RandomBoosterDraft.java @@ -50,28 +50,11 @@ public class RandomBoosterDraft extends BoosterDraft { resetBoosters(); } - @Override - public void start() { - while (!isAbort() && boosterNum < numberBoosters) { - openBooster(); - while (!isAbort() && pickCards()) { - if (boosterNum % 2 == 1) { - passLeft(); - } else { - passRight(); - } - fireUpdatePlayersEvent(); - } - } - resetBufferedCards(); - this.fireEndDraftEvent(); - } - @Override protected void openBooster() { if (boosterNum < numberBoosters) { for (DraftPlayer player: players.values()) { - player.setBooster(getNextBooster().createBooster()); + player.setBooster(getNextBooster().create15CardBooster()); } } boosterNum++; From 4eb52fdc917d90b669281746efaca06bc847b5c7 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 15 Jul 2015 08:27:44 +0200 Subject: [PATCH 2/4] Xmage 1.4.2v3 --- Mage.Common/src/mage/utils/MageVersion.java | 2 +- Mage/src/mage/cards/repository/CardRepository.java | 2 +- Utils/release/getting_implemented_cards.txt | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index bab39e2485..4800c7c1d4 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 2; - public final static String MAGE_VERSION_MINOR_PATCH = "v2"; + public final static String MAGE_VERSION_MINOR_PATCH = "v3"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage/src/mage/cards/repository/CardRepository.java b/Mage/src/mage/cards/repository/CardRepository.java index 3fa5172d4f..7c073ea5aa 100644 --- a/Mage/src/mage/cards/repository/CardRepository.java +++ b/Mage/src/mage/cards/repository/CardRepository.java @@ -60,7 +60,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 41; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 26; + private static final long CARD_CONTENT_VERSION = 29; private final Random random = new Random(); private Dao cardDao; diff --git a/Utils/release/getting_implemented_cards.txt b/Utils/release/getting_implemented_cards.txt index 86a8ba4c88..c23eb917f1 100644 --- a/Utils/release/getting_implemented_cards.txt +++ b/Utils/release/getting_implemented_cards.txt @@ -149,9 +149,11 @@ git log cd0cba6ec7d8799bb85247b7b4f5d545e170b093..HEAD --diff-filter=A --name-st since 1.4.2.v1 git log 0b26aaff6ec033a538179bf607b1c7a7736aedb2..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt -since 1.4.2.v1 +since 1.4.2.v2 git log 8d5137e40ebe1c029e737ef475935ff7cc40bb64..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt +since 1.4.2.v3 +git log 60c7a2b34b5dd9a64bd415b65424a559294cf52b..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt 3. Copy added_cards.txt to trunk\Utils folder 4. Run script: From 3bac7b550c62fd91a5d97804550cbc78402935fc Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 15 Jul 2015 16:54:31 +0200 Subject: [PATCH 3/4] Added a test for storm with flashback. --- .../cards/abilities/keywords/StormTest.java | 90 +++++++++++++------ 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java index 6caa1dcf76..de7dbf4862 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package org.mage.test.cards.abilities.keywords; import mage.constants.PhaseStep; @@ -41,23 +40,20 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class StormTest extends CardTestPlayerBase { /** - * 702.39. Storm - * 702.39a Storm is a triggered ability that functions on the stack. “Storm” means “When you cast this - * spell, put a copy of it onto the stack for each other spell that was cast before it this turn. If the + * 702.39. Storm 702.39a Storm is a triggered ability that functions on the + * stack. “Storm” means “When you cast this spell, put a copy of it onto the + * stack for each other spell that was cast before it this turn. If the * spell has any targets, you may choose new targets for any of the copies.” - * 702.39b If a spell has multiple instances of storm, each triggers separately. - * + * 702.39b If a spell has multiple instances of storm, each triggers + * separately. + * */ - /** - * Grapeshot - * Sorcery, 1R (2) - * Grapeshot deals 1 damage to target creature or player. - * Storm (When you cast this spell, copy it for each spell cast before it - * this turn. You may choose new targets for the copies.) - * + * Grapeshot Sorcery, 1R (2) Grapeshot deals 1 damage to target creature or + * player. Storm (When you cast this spell, copy it for each spell cast + * before it this turn. You may choose new targets for the copies.) + * */ - @Test public void testStorm1x() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); @@ -105,7 +101,7 @@ public class StormTest extends CardTestPlayerBase { assertLife(playerB, 7); } - + @Test public void testStorm4x() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6); @@ -123,7 +119,7 @@ public class StormTest extends CardTestPlayerBase { assertLife(playerB, 3); } - + @Test public void testNoStorm() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); @@ -136,13 +132,13 @@ public class StormTest extends CardTestPlayerBase { assertLife(playerB, 19); } - + /** - * If a spell with storm gets countered, the strom trigger is also stifled, which isn't how its supposed to work. - * For example a Chalic of the Void set to 1 counters Flusterstorm and also counters the storm trigger, which shouldn't happen + * If a spell with storm gets countered, the strom trigger is also stifled, + * which isn't how its supposed to work. For example a Chalic of the Void + * set to 1 counters Flusterstorm and also counters the storm trigger, which + * shouldn't happen */ - - @Test public void testStormSpellCountered() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); @@ -155,20 +151,21 @@ public class StormTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Island", 2); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); - + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Counterspell", "Grapeshot"); - + setStopAt(1, PhaseStep.END_TURN); execute(); assertLife(playerB, 16); // 3 (Lightning Bolt) + 1 from Storm copied Grapeshot } - + /** - * I provide a game log fo the issue with storm mentioned earlier. I guess Pyromancer Ascension is a culprit. - * - * + * I provide a game log fo the issue with storm mentioned earlier. I guess + * Pyromancer Ascension is a culprit. + * + * */ @Test public void testStormAndPyromancerAscension() { @@ -178,7 +175,7 @@ public class StormTest extends CardTestPlayerBase { // Whenever you cast an instant or sorcery spell while Pyromancer Ascension has two or more quest counters on it, you may copy that spell. You may choose new targets for the copy. addCard(Zone.BATTLEFIELD, playerA, "Pyromancer Ascension", 1); // Grapeshot deals 1 damage to target creature or player. - Sorcery {1}{R} - // Storm (When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.) + // Storm (When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.) addCard(Zone.LIBRARY, playerA, "Grapeshot", 2); skipInitShuffling(); // Look at the top two cards of your library. Put one of them into your hand and the other on the bottom of your library. @@ -198,5 +195,40 @@ public class StormTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Grapeshot", 1); assertCounterCount("Pyromancer Ascension", CounterType.QUEST, 2); assertLife(playerB, 8); // 6 from the Shocks + 5 from Grapeshot + 1 from Pyromancer Ascencsion copy - } + } + + /** + * I provide a game log fo the issue with storm mentioned earlier. I guess + * Pyromancer Ascension is a culprit. + * + * + */ + @Test + public void testStormAndFlshback() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + // Geistflame deals 1 damage to target creature or player. + // Flashback {3}{R} (You may cast this card from your graveyard for its flashback cost. Then exile it.) + addCard(Zone.HAND, playerA, "Geistflame", 2); // {R} + addCard(Zone.LIBRARY, playerA, "Grapeshot", 2); + skipInitShuffling(); + // Look at the top two cards of your library. Put one of them into your hand and the other on the bottom of your library. + addCard(Zone.HAND, playerA, "Sleight of Hand"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sleight of Hand"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Geistflame", playerB); + activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "Flashback {3}{R}"); + addTarget(playerA, playerB); + castSpell(1, PhaseStep.END_COMBAT, playerA, "Geistflame", playerB); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertExileCount("Geistflame", 1); + assertGraveyardCount(playerA, "Geistflame", 1); + assertGraveyardCount(playerA, "Grapeshot", 1); + assertLife(playerB, 12); // 3 from the Geistflame + 5 from Grapeshot + } + } From cd354bacc3259c49e9a2d3703989f5a4c0ab9e5e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 15 Jul 2015 17:24:18 +0200 Subject: [PATCH 4/4] Added a test. --- .../abilities/keywords/DeathtouchTest.java | 83 ++++++++++++++----- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DeathtouchTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DeathtouchTest.java index 72766b529a..1f9a2f19cf 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DeathtouchTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DeathtouchTest.java @@ -37,32 +37,31 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * @author LevelX2 */ public class DeathtouchTest extends CardTestPlayerBase { - + @Test public void simpleDeathtouchDuringCombat() { addCard(Zone.BATTLEFIELD, playerA, "Archangel of Thune"); // Creature - Rat 1/1 // Deathtouch addCard(Zone.BATTLEFIELD, playerB, "Typhoid Rats"); - - + attack(2, playerB, "Typhoid Rats"); block(2, playerA, "Archangel of Thune", "Typhoid Rats"); - + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); execute(); - + assertLife(playerA, 23); assertLife(playerB, 20); - + assertGraveyardCount(playerA, "Archangel of Thune", 1); assertGraveyardCount(playerB, "Typhoid Rats", 1); } - + /** - * Checks if a creature getting damage from Marath abilitity dies - * from Deathtouch, if Marath is equiped with Deathtouch giving Equipment - * and Marath dies from removing the +1/+1 counters. + * Checks if a creature getting damage from Marath abilitity dies from + * Deathtouch, if Marath is equiped with Deathtouch giving Equipment and + * Marath dies from removing the +1/+1 counters. */ @Test public void testMarathWillOfTheWild() { @@ -73,21 +72,20 @@ public class DeathtouchTest extends CardTestPlayerBase { // Equipped creature has deathtouch and lifelink. addCard(Zone.BATTLEFIELD, playerA, "Basilisk Collar"); /* - {R}{G}{W} Legendary Creature - Elemental Beast - Marath, Will of the Wild enters the battlefield with a number of +1/+1 counters on - it equal to the amount of mana spent to cast it. - {X}, Remove X +1/+1 counters from Marath: Choose one - - * Put X +1/+1 counters on target creature - * Marath deals X damage to target creature or player - * Put an X/X green Elemental creature token onto the battlefield. X can't be 0 - */ + {R}{G}{W} Legendary Creature - Elemental Beast + Marath, Will of the Wild enters the battlefield with a number of +1/+1 counters on + it equal to the amount of mana spent to cast it. + {X}, Remove X +1/+1 counters from Marath: Choose one - + * Put X +1/+1 counters on target creature + * Marath deals X damage to target creature or player + * Put an X/X green Elemental creature token onto the battlefield. X can't be 0 + */ addCard(Zone.HAND, playerA, "Marath, Will of the Wild", 1); - + addCard(Zone.BATTLEFIELD, playerB, "Archangel of Thune"); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN , playerA, "Marath, Will of the Wild"); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Marath, Will of the Wild"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {2}", "Marath, Will of the Wild"); activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{X},Remove X +1/+1 counters from Marath", "Archangel of Thune"); @@ -104,6 +102,45 @@ public class DeathtouchTest extends CardTestPlayerBase { assertLife(playerB, 20); } - + @Test + public void testMarathWillOfTheWildEleshNorn() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Zone.BATTLEFIELD, playerA, "Forest"); + addCard(Zone.BATTLEFIELD, playerA, "Plains"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10); + + // Equipped creature has deathtouch and lifelink. + addCard(Zone.BATTLEFIELD, playerA, "Basilisk Collar"); + /* + {R}{G}{W} Legendary Creature - Elemental Beast + Marath, Will of the Wild enters the battlefield with a number of +1/+1 counters on + it equal to the amount of mana spent to cast it. + {X}, Remove X +1/+1 counters from Marath: Choose one - + * Put X +1/+1 counters on target creature + * Marath deals X damage to target creature or player + * Put an X/X green Elemental creature token onto the battlefield. X can't be 0 + */ + addCard(Zone.HAND, playerA, "Marath, Will of the Wild", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Elesh Norn, Grand Cenobite"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Marath, Will of the Wild"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {2}", "Marath, Will of the Wild"); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{X},Remove X +1/+1 counters from Marath", "Elesh Norn, Grand Cenobite"); + setModeChoice(playerA, "2"); // Marath deals X damage to target creature or player + setChoice(playerA, "X=1"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Marath, Will of the Wild", 0); // died because he's 0/0 + assertPermanentCount(playerB, "Elesh Norn, Grand Cenobite", 0); // died from deathtouch + + assertLife(playerA, 21); // +1 from lifelink doing 1 damage with Marath to Elesh Norn + assertLife(playerB, 20); + + } }