diff --git a/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java index fc24968fc7..14ec6de8b2 100644 --- a/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java +++ b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java @@ -85,7 +85,7 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener { } public void loadBooster(CardsView booster, BigCard bigCard) { - if (booster instanceof CardsView && booster.size() == 0) { + if (booster instanceof CardsView && booster.isEmpty()) { emptyGrid = true; } else { if (!emptyGrid) { diff --git a/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/ChoiceDialog.java b/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/ChoiceDialog.java index 19ac164198..cb6c9779b1 100644 --- a/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/ChoiceDialog.java +++ b/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/ChoiceDialog.java @@ -126,7 +126,7 @@ public class ChoiceDialog extends IDialogPanel { } private void displayCards(CardsView cards, UUID gameId, BigCard bigCard) { - if (cards.size() == 0) { + if (cards.isEmpty()) { return; } diff --git a/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java b/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java index 9a8f65f618..9c239e29bc 100644 --- a/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java +++ b/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java @@ -103,7 +103,7 @@ public class StackDialog extends IDialogPanel { private void displayStack(CardsView cards, UUID gameId, BigCard bigCard) { - if (cards == null || cards.size() == 0) { + if (cards == null || cards.isEmpty()) { return; } diff --git a/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java index fa5db9f4a1..868ee2818e 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java @@ -259,7 +259,7 @@ public class ResetPasswordDialog extends MageDialog { }// //GEN-END:initComponents private void btnGetAuthTokenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGetAuthTokenActionPerformed - if (this.txtEmail.getText().length() == 0) { + if (this.txtEmail.getText().isEmpty()) { MageFrame.getInstance().showError("Please enter an email address."); return; } @@ -275,15 +275,15 @@ public class ResetPasswordDialog extends MageDialog { }//GEN-LAST:event_btnGetAuthTokenActionPerformed private void btnSubmitNewPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubmitNewPasswordActionPerformed - if (this.txtEmail.getText().length() == 0) { + if (this.txtEmail.getText().isEmpty()) { MageFrame.getInstance().showError("Please enter an email address."); return; } - if (this.txtAuthToken.getText().length() == 0) { + if (this.txtAuthToken.getText().isEmpty()) { MageFrame.getInstance().showError("Please enter an auth token."); return; } - if (this.txtPassword.getText().length() == 0) { + if (this.txtPassword.getText().isEmpty()) { MageFrame.getInstance().showError("Please enter a new password."); return; } diff --git a/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java b/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java index b38caafc3c..295c360b98 100644 --- a/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java @@ -166,7 +166,7 @@ public class TournamentPlayerPanel extends javax.swing.JPanel { private void cbPlayerTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPlayerTypeActionPerformed if (!this.cbPlayerType.getSelectedItem().equals("Human")) { this.pnlPlayerName.setVisible(true); - if (this.txtPlayerName.getText().length() == 0) { + if (this.txtPlayerName.getText().isEmpty()) { this.txtPlayerName.setText("Computer " + this.lblPlayerNum.getText()); } } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java b/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java index 526eec50cb..cd62bb3041 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java @@ -153,7 +153,7 @@ public class GlowText extends JLabel { @Override public void paint(Graphics g) { - if (getText().length() == 0) { + if (getText().isEmpty()) { return; } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java index 6b62e3f738..c5d11d10a8 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java @@ -217,7 +217,7 @@ public class ManaSymbols { loadSymbolsImages(symbolWidth); } Map sizedSymbols = manaImages.get(symbolWidth); - if (manaCost.length() == 0) { + if (manaCost.isEmpty()) { return; } manaCost = manaCost.replace("\\", ""); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 41a2fe6bdd..0ff1ec0105 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -98,7 +98,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab ArrayList cards = getNeededCards(allCards); /* - * if (cards == null || cards.size() == 0) { + * if (cards == null || cards.isEmpty()) { * JOptionPane.showMessageDialog(null, * "All card pictures have been downloaded."); return; } */ diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index 4960fdfd74..a58b7442f7 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -27,22 +27,6 @@ */ package mage.remote; -import java.io.IOException; -import java.lang.reflect.UndeclaredThrowableException; -import java.net.Authenticator; -import java.net.ConnectException; -import java.net.MalformedURLException; -import java.net.PasswordAuthentication; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; import mage.MageException; import mage.cards.decks.DeckCardLists; import mage.cards.decks.InvalidDeckException; @@ -62,22 +46,9 @@ import mage.interfaces.ServerState; import mage.interfaces.callback.ClientCallback; import mage.players.net.UserData; import mage.utils.CompressUtil; -import mage.view.DraftPickView; -import mage.view.GameTypeView; -import mage.view.MatchView; -import mage.view.RoomUsersView; -import mage.view.TableView; -import mage.view.TournamentTypeView; -import mage.view.TournamentView; -import mage.view.UserView; +import mage.view.*; import org.apache.log4j.Logger; -import org.jboss.remoting.CannotConnectException; -import org.jboss.remoting.Client; -import org.jboss.remoting.ConnectionListener; -import org.jboss.remoting.ConnectionValidator; -import org.jboss.remoting.InvocationFailureException; -import org.jboss.remoting.InvokerLocator; -import org.jboss.remoting.Remoting; +import org.jboss.remoting.*; import org.jboss.remoting.callback.Callback; import org.jboss.remoting.callback.HandleCallbackException; import org.jboss.remoting.callback.InvokerCallbackHandler; @@ -85,6 +56,12 @@ import org.jboss.remoting.transport.bisocket.Bisocket; import org.jboss.remoting.transport.socket.SocketWrapper; import org.jboss.remoting.transporter.TransporterClient; +import java.io.IOException; +import java.lang.reflect.UndeclaredThrowableException; +import java.net.*; +import java.util.*; +import java.util.concurrent.TimeUnit; + /** * * @author BetaSteward_at_googlemail.com diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index 39b0266060..fff24fdf6b 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -185,7 +185,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { if (logger.isInfoEnabled()) { printOutState(game); } - if (actions.size() == 0) { + if (actions.isEmpty()) { calculateActions(game); } act(game); @@ -351,7 +351,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { /* * // Try to fix horizon effect if (root.combat == null || - * root.combat.getAttackers().size() == 0) { + * root.combat.getAttackers().isEmpty()) { * FilterCreatureForAttack attackFilter = new * FilterCreatureForAttack(); * attackFilter.getControllerId().add(playerId); List diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java index 1f3069ac0c..a49c7ca7a0 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java @@ -105,7 +105,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { case PRECOMBAT_MAIN: if (game.getActivePlayerId().equals(playerId)) { printOutState(game); - if (actions.size() == 0) { + if (actions.isEmpty()) { logger.info("Sim Calculate pre combat actions ----------------------------------------------------- "); calculatePreCombatActions(game); } @@ -122,7 +122,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { case DECLARE_ATTACKERS: if (!game.getActivePlayerId().equals(playerId)) { printOutState(game); - if (actions.size() == 0) { + if (actions.isEmpty()) { logger.info("Sim Calculate declare attackers actions ----------------------------------------------------- "); calculatePreCombatActions(game); } @@ -142,7 +142,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { case POSTCOMBAT_MAIN: // if (game.getActivePlayerId().equals(playerId)) { printOutState(game); - if (actions.size() == 0) { + if (actions.isEmpty()) { calculatePostCombatActions(game); } act(game); diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java index bc43063666..3141c5227e 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java @@ -117,7 +117,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player { case COMBAT_DAMAGE: case END_COMBAT: case POSTCOMBAT_MAIN: - if (actions.size() == 0) { + if (actions.isEmpty()) { calculateActions(game); } act(game); @@ -131,7 +131,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player { } protected void act(Game game) { - if (actions == null || actions.size() == 0) + if (actions == null || actions.isEmpty()) pass(game); else { boolean usedStack = false; diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java index c01bed8a68..2ceb791e15 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java @@ -78,7 +78,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { return false; case PRECOMBAT_MAIN: if (game.getActivePlayerId().equals(playerId)) { - if (actions.size() == 0) { + if (actions.isEmpty()) { calculatePreCombatActions(game); } act(game); @@ -92,7 +92,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { return false; case DECLARE_ATTACKERS: if (!game.getActivePlayerId().equals(playerId)) { - if (actions.size() == 0) { + if (actions.isEmpty()) { calculatePreCombatActions(game); } act(game); @@ -109,7 +109,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { return false; case POSTCOMBAT_MAIN: if (game.getActivePlayerId().equals(playerId)) { - if (actions.size() == 0) { + if (actions.isEmpty()) { calculatePostCombatActions(game); } act(game); diff --git a/Mage.Server/src/main/java/mage/server/GmailClient.java b/Mage.Server/src/main/java/mage/server/GmailClient.java index 3edc2f307e..daf6b9d694 100644 --- a/Mage.Server/src/main/java/mage/server/GmailClient.java +++ b/Mage.Server/src/main/java/mage/server/GmailClient.java @@ -63,7 +63,7 @@ public class GmailClient { } public static boolean sendMessage(String email, String subject, String text) { - if (email.length() == 0) { + if (email.isEmpty()) { logger.info("Email is not sent because the address is empty"); return false; } diff --git a/Mage.Server/src/main/java/mage/server/MailClient.java b/Mage.Server/src/main/java/mage/server/MailClient.java index 9c7ef61458..16c8f3ae59 100644 --- a/Mage.Server/src/main/java/mage/server/MailClient.java +++ b/Mage.Server/src/main/java/mage/server/MailClient.java @@ -15,7 +15,7 @@ public class MailClient { private static final Logger logger = Logger.getLogger(Main.class); public static boolean sendMessage(String email, String subject, String text) { - if (email.length() == 0) { + if (email.isEmpty()) { logger.info("Email is not sent because the address is empty"); return false; } diff --git a/Mage.Server/src/main/java/mage/server/MailgunClient.java b/Mage.Server/src/main/java/mage/server/MailgunClient.java index 77ba777783..45b3557aa6 100644 --- a/Mage.Server/src/main/java/mage/server/MailgunClient.java +++ b/Mage.Server/src/main/java/mage/server/MailgunClient.java @@ -14,7 +14,7 @@ public class MailgunClient { private static final Logger logger = Logger.getLogger(Main.class); public static boolean sendMessage(String email, String subject, String text) { - if (email.length() == 0) { + if (email.isEmpty()) { logger.info("Email is not sent because the address is empty"); return false; } diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 4bae78ba57..0e40dd5d1a 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -55,7 +55,7 @@ public class SystemUtil { try { while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); - if (line.trim().length() == 0 || line.startsWith("#")) { + if (line.trim().isEmpty() || line.startsWith("#")) { continue; } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java b/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java index 858c6b9a85..3b6f2e3747 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java @@ -95,7 +95,7 @@ class CreaturesYouControlBecomesTargetTriggeredAbility extends TriggeredAbilityI if (object != null && object instanceof Spell) { Card c = (Spell) object; if (c.getCardType().contains(CardType.INSTANT) || c.getCardType().contains(CardType.SORCERY)) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); } diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java index 35a67b4671..8600bab84d 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java @@ -38,12 +38,7 @@ import mage.abilities.effects.common.AttachEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.WatcherScope; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -54,6 +49,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; + /** * * @author LevelX2 @@ -159,9 +155,8 @@ class DamagedByEnchantedWatcher extends Watcher { if (enchantment != null && enchantment.getAttachedTo() != null) { if (enchantment.getAttachedTo().equals(event.getSourceId())) { MageObjectReference mor = new MageObjectReference(event.getTargetId(), game); - if (!damagedCreatures.contains(mor)) { damagedCreatures.add(mor); - } + } } } diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/MinamosMeddling.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/MinamosMeddling.java index 650d87ccce..a6cd389624 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/MinamosMeddling.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/MinamosMeddling.java @@ -46,6 +46,9 @@ import mage.game.stack.Spell; import mage.players.Player; import mage.target.TargetSpell; +import java.util.UUID; + + /** * * @author LevelX2 @@ -103,7 +106,7 @@ class MinamosMeddlingCounterTargetEffect extends OneShotEffect { for (SpellAbility spellAbility : spell.getSpellAbilities()) { if (spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE)) { for (Card card: spellController.getHand().getCards(game)) { - if (card.getName().equals(spellAbility.getCardName()) && !cardsToDiscard.contains(card.getId())) { + if (card.getName().equals(spellAbility.getCardName())) { cardsToDiscard.add(card); } } diff --git a/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java b/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java index b17c9bef2e..6488dad034 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java @@ -34,16 +34,12 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.WatcherScope; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.watchers.Watcher; + /** * * @author LevelX2 @@ -96,9 +92,8 @@ class SpiritOfTheLabyrinthWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.DREW_CARD ) { - if (!playersThatDrewCard.contains(event.getPlayerId())) { playersThatDrewCard.add(event.getPlayerId()); - } + } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java b/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java index 3291410245..629ba1884b 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java @@ -102,7 +102,7 @@ class NezumiGraverobberFlipEffect extends OneShotEffect { if (card != null) { Player player = game.getPlayer(card.getOwnerId()); if (player != null) { - if (player.getGraveyard().size() == 0) { + if (player.getGraveyard().isEmpty()) { return new FlipSourceEffect(new NighteyesTheDesecratorToken()).apply(game, source); } } diff --git a/Mage.Sets/src/mage/sets/commander/DesecratorHag.java b/Mage.Sets/src/mage/sets/commander/DesecratorHag.java index fd5824cead..675d7281d0 100644 --- a/Mage.Sets/src/mage/sets/commander/DesecratorHag.java +++ b/Mage.Sets/src/mage/sets/commander/DesecratorHag.java @@ -112,7 +112,7 @@ class DesecratorHagEffect extends OneShotEffect { } } } - if (cards.size() == 0) { + if (cards.isEmpty()) { return true; } if (cards.size() > 1 diff --git a/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java b/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java index 41a7479fc1..4065727010 100644 --- a/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java +++ b/Mage.Sets/src/mage/sets/commander2013/JelevaNephaliasScourge.java @@ -160,7 +160,6 @@ class JelevaNephaliasCastEffect extends OneShotEffect { if (controller.choose(Outcome.PlayForFree, exileZone, target, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { - game.getExile().removeCard(card, game); return controller.cast(card.getSpellAbility(), game, true); } } diff --git a/Mage.Sets/src/mage/sets/commander2014/CrownOfDoom.java b/Mage.Sets/src/mage/sets/commander2014/CrownOfDoom.java index 009ef2e3e1..da2d721fb0 100644 --- a/Mage.Sets/src/mage/sets/commander2014/CrownOfDoom.java +++ b/Mage.Sets/src/mage/sets/commander2014/CrownOfDoom.java @@ -49,7 +49,7 @@ import mage.constants.Zone; import mage.filter.FilterPlayer; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.filter.predicate.other.OwnerIdPredicate; +import mage.filter.predicate.other.PlayerIdPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; @@ -86,7 +86,7 @@ public class CrownOfDoom extends CardImpl { if (sourceCard != null) { ability.getTargets().clear(); FilterPlayer filter = new FilterPlayer("player other than " + sourceCard.getIdName() + "'s owner"); - filter.add(Predicates.not(new OwnerIdPredicate(sourceCard.getOwnerId()))); + filter.add(Predicates.not(new PlayerIdPredicate(sourceCard.getOwnerId()))); ability.addTarget(new TargetPlayer(1, 1, false, filter)); } } diff --git a/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java b/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java index e0a08a9923..7f372c4baf 100644 --- a/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java +++ b/Mage.Sets/src/mage/sets/conspiracytakethecrown/LeovoldEmissaryOfTrest.java @@ -43,6 +43,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.watchers.Watcher; + /** * * @author maxlebedev @@ -99,9 +100,8 @@ class LeovoldEmissaryOfTrestWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.DREW_CARD ) { - if (!playersThatDrewCard.contains(event.getPlayerId())) { playersThatDrewCard.add(event.getPlayerId()); - } + } } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/RalZarek.java b/Mage.Sets/src/mage/sets/dragonsmaze/RalZarek.java index 1f12e5f5f2..285893c4a6 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/RalZarek.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/RalZarek.java @@ -31,19 +31,23 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.turn.TurnMod; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreatureOrPlayer; +import mage.target.targetpointer.SecondTargetPointer; /** * @@ -51,6 +55,12 @@ import mage.target.common.TargetCreatureOrPlayer; */ public class RalZarek extends CardImpl { + private static final FilterPermanent secondFilter = new FilterPermanent("another target permanent"); + + static { + secondFilter.add(new AnotherTargetPredicate(2)); + } + public RalZarek(UUID ownerId) { super(ownerId, 94, "Ral Zarek", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{2}{U}{R}"); this.expansionSetCode = "DGM"; @@ -59,8 +69,17 @@ public class RalZarek extends CardImpl { this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); // +1: Tap target permanent, then untap another target permanent. - LoyaltyAbility ability1 = new LoyaltyAbility(new RalZarekTapUntapEffect(), 1); - ability1.addTarget(new TargetPermanent(2, 2, new FilterPermanent(), false)); + LoyaltyAbility ability1 = new LoyaltyAbility(new TapTargetEffect(), 1); + TargetPermanent firstTarget = new TargetPermanent(); + firstTarget.setTargetTag(1); + ability1.addTarget(firstTarget); + Effect effect = new UntapTargetEffect(); + effect.setText(", then untap another target permanent"); + effect.setTargetPointer(new SecondTargetPointer()); + ability1.addEffect(effect); + TargetPermanent secondTarget = new TargetPermanent(secondFilter); + secondTarget.setTargetTag(2); + ability1.addTarget(secondTarget); this.addAbility(ability1); // -2: Ral Zarek deals 3 damage to target creature or player. @@ -83,45 +102,6 @@ public class RalZarek extends CardImpl { } } -class RalZarekTapUntapEffect extends OneShotEffect { - - public RalZarekTapUntapEffect() { - super(Outcome.Tap); - this.staticText = "Tap target permanent, then untap another target permanent"; - } - - public RalZarekTapUntapEffect(final RalZarekTapUntapEffect effect) { - super(effect); - } - - @Override - public RalZarekTapUntapEffect copy() { - return new RalZarekTapUntapEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - int i = 0; - for (UUID targetId : source.getTargets().get(0).getTargets()) { - i++; - Permanent permanent = game.getPermanent(targetId); - if (permanent != null) { - if (i == 1) { - permanent.tap(game); - } - if (i == 2) { - permanent.untap(game); - } - } - } - return true; - } - return false; - } -} - class RalZarekExtraTurnsEffect extends OneShotEffect { public RalZarekExtraTurnsEffect() { diff --git a/Mage.Sets/src/mage/sets/eventide/RekindledFlame.java b/Mage.Sets/src/mage/sets/eventide/RekindledFlame.java index 97606a925f..1b3d8767e8 100644 --- a/Mage.Sets/src/mage/sets/eventide/RekindledFlame.java +++ b/Mage.Sets/src/mage/sets/eventide/RekindledFlame.java @@ -85,7 +85,7 @@ class OpponentHasNoCardsInHandCondition implements Condition { if (player != null) { for (UUID playerId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(playerId); - if (opponent != null && opponent.getHand().size() == 0) { + if (opponent != null && opponent.getHand().isEmpty()) { return true; } } diff --git a/Mage.Sets/src/mage/sets/innistrad/GavonyTownship.java b/Mage.Sets/src/mage/sets/innistrad/GavonyTownship.java index 0fecbaf4dd..81e1ecd792 100644 --- a/Mage.Sets/src/mage/sets/innistrad/GavonyTownship.java +++ b/Mage.Sets/src/mage/sets/innistrad/GavonyTownship.java @@ -1,5 +1,6 @@ package mage.sets.innistrad; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -13,14 +14,16 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; -import java.util.UUID; - public class GavonyTownship extends CardImpl { + public GavonyTownship(UUID ownerId) { super(ownerId, 239, "Gavony Township", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "ISD"; + // {T}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); + + // {2}{G}{W}, {T}: Put a +1/+1 counter on each creature you control. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent("creature you control")), new ManaCostsImpl("{2}{G}{W}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/kaladesh/AcrobaticManeuver.java b/Mage.Sets/src/mage/sets/kaladesh/AcrobaticManeuver.java new file mode 100644 index 0000000000..551fc98767 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AcrobaticManeuver.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ExileTargetForSourceEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class AcrobaticManeuver extends CardImpl { + + public AcrobaticManeuver(UUID ownerId) { + super(ownerId, 1, "Acrobatic Maneuver", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}"); + this.expansionSetCode = "KLD"; + + // Exile target creature you control, then return that card to the battlefield under its owner's control. + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + Effect effect = new ExileTargetForSourceEffect(); + effect.setApplyEffectsAfter(); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, true)); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public AcrobaticManeuver(final AcrobaticManeuver card) { + super(card); + } + + @Override + public AcrobaticManeuver copy() { + return new AcrobaticManeuver(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/AerialResponder.java b/Mage.Sets/src/mage/sets/kaladesh/AerialResponder.java new file mode 100644 index 0000000000..143b3e3b2a --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AerialResponder.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class AerialResponder extends CardImpl { + + public AerialResponder(UUID ownerId) { + super(ownerId, 2, "Aerial Responder", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dwarf"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + } + + public AerialResponder(final AerialResponder card) { + super(card); + } + + @Override + public AerialResponder copy() { + return new AerialResponder(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/AetherstormRoc.java b/Mage.Sets/src/mage/sets/kaladesh/AetherstormRoc.java new file mode 100644 index 0000000000..e4b3108de4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AetherstormRoc.java @@ -0,0 +1,102 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class AetherstormRoc extends CardImpl { + + private final UUID originalId; + + public AetherstormRoc(UUID ownerId) { + super(ownerId, 3, "Aetherstorm Roc", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Bird"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E}. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new GetEnergyCountersControllerEffect(1), new FilterCreaturePermanent("{this} or another creature"))); + + // Whenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls. + DoIfCostPaid doIfCostPaidEffect = new DoIfCostPaid(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new PayEnergyCost(2)); + doIfCostPaidEffect.addEffect(new TapTargetEffect()); + Ability ability = new AttacksTriggeredAbility(doIfCostPaidEffect, false, + "Whenever {this} attacks you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls."); + ability.addTarget(new TargetCreaturePermanent(0, 1, new FilterCreaturePermanent("creature defending player controls"), false)); + originalId = ability.getOriginalId(); + this.addAbility(ability); + + } + + public AetherstormRoc(final AetherstormRoc card) { + super(card); + this.originalId = card.originalId; + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability.getOriginalId().equals(originalId)) { + ability.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); + filter.add(new ControllerIdPredicate(defenderId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); + ability.addTarget(target); + } + } + + @Override + public AetherstormRoc copy() { + return new AetherstormRoc(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/AngelOfInvention.java b/Mage.Sets/src/mage/sets/kaladesh/AngelOfInvention.java new file mode 100644 index 0000000000..5e3d5a473d --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AngelOfInvention.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FabricateAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class AngelOfInvention extends CardImpl { + + public AngelOfInvention(UUID ownerId) { + super(ownerId, 4, "Angel of Invention", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Angel"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + // Fabricate 2 + this.addAbility(new FabricateAbility(2)); + // Other creatures you control get +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, true))); + } + + public AngelOfInvention(final AngelOfInvention card) { + super(card); + } + + @Override + public AngelOfInvention copy() { + return new AngelOfInvention(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java b/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java new file mode 100644 index 0000000000..9d2d7e708e --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/BomatCourier.java @@ -0,0 +1,144 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardHandCost; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author emerald000 + */ +public class BomatCourier extends CardImpl { + + public BomatCourier(UUID ownerId) { + super(ownerId, 199, "Bomat Courier", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Bomat Courier attacks, exile the top card of your library face down. + this.addAbility(new AttacksTriggeredAbility(new BomatCourierExileEffect(), false)); + + // {R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BomatCourierReturnEffect(), new ColoredManaCost(ColoredManaSymbol.R)); + ability.addCost(new DiscardHandCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public BomatCourier(final BomatCourier card) { + super(card); + } + + @Override + public BomatCourier copy() { + return new BomatCourier(this); + } +} + +class BomatCourierExileEffect extends OneShotEffect { + + BomatCourierExileEffect() { + super(Outcome.Exile); + this.staticText = "exile the top card of your library face down"; + } + + BomatCourierExileEffect(final BomatCourierExileEffect effect) { + super(effect); + } + + @Override + public BomatCourierExileEffect copy() { + return new BomatCourierExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + UUID exileZoneId = CardUtil.getCardExileZoneId(game, source); + card.setFaceDown(true, game); + controller.moveCardsToExile(card, source, game, false, exileZoneId, "Bomat Courier"); + card.setFaceDown(true, game); + return true; + } + } + return false; + } +} + +class BomatCourierReturnEffect extends OneShotEffect { + + BomatCourierReturnEffect() { + super(Outcome.DrawCard); + this.staticText = "Put all cards exiled with {this} into their owners' hands"; + } + + BomatCourierReturnEffect(final BomatCourierReturnEffect effect) { + super(effect); + } + + @Override + public BomatCourierReturnEffect copy() { + return new BomatCourierReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + return controller.moveCards(game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId(), true)), Zone.HAND, source, game); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ConsulateSurveillance.java b/Mage.Sets/src/mage/sets/kaladesh/ConsulateSurveillance.java new file mode 100644 index 0000000000..a05506d8b2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ConsulateSurveillance.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.effects.common.PreventAllDamageFromChosenSourceToYouEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterObject; + +/** + * + * @author LevelX2 + */ +public class ConsulateSurveillance extends CardImpl { + + public ConsulateSurveillance(UUID ownerId) { + super(ownerId, 10, "Consulate Surveillance", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + this.expansionSetCode = "KLD"; + + // When Consulate Surveillance enters the battlefield, you get {E}{E}{E}{E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(4))); + + // Pay {E}{E}: Prevent all damage that would be dealt to you this turn by a source of your choice. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, + new PreventAllDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, new FilterObject("source"), false), + new PayEnergyCost(2))); + + } + + public ConsulateSurveillance(final ConsulateSurveillance card) { + super(card); + } + + @Override + public ConsulateSurveillance copy() { + return new ConsulateSurveillance(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/Demolish.java b/Mage.Sets/src/mage/sets/kaladesh/Demolish.java new file mode 100644 index 0000000000..fbd34e61f0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/Demolish.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class Demolish extends mage.sets.tenthedition.Demolish { + + public Demolish(UUID ownerId) { + super(ownerId); + this.cardNumber = "113"; + this.expansionSetCode = "KLD"; + } + + public Demolish(final Demolish card) { + super(card); + } + + @Override + public Demolish copy() { + return new Demolish(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/DemonOfDarkSchemes.java b/Mage.Sets/src/mage/sets/kaladesh/DemonOfDarkSchemes.java new file mode 100644 index 0000000000..218f624fca --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/DemonOfDarkSchemes.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author fireshoes + */ +public class DemonOfDarkSchemes extends CardImpl { + + public DemonOfDarkSchemes(UUID ownerId) { + super(ownerId, 73, "Demon of Dark Schemes", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Demon"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Demon of Dark Schemes enters the battlefield, all other creatures get -2/-2 until end of turn. + Effect effect = new BoostAllEffect(-2, -2, Duration.EndOfTurn, true); + effect.setText("all other creatures get -2/-2 until end of turn"); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect, false)); + + // Whenever another creature dies, you get {E}. + this.addAbility(new DiesCreatureTriggeredAbility(new GetEnergyCountersControllerEffect(1), false, true)); + + // {2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefield under your control tapped. + effect = new ReturnFromGraveyardToBattlefieldTargetEffect(true); + effect.setText("Put target creature card from a graveyard onto the battlefield under your control tapped"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}{B}")); + ability.addCost(new PayEnergyCost(4)); + ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); + this.addAbility(ability); + } + + public DemonOfDarkSchemes(final DemonOfDarkSchemes card) { + super(card); + } + + @Override + public DemonOfDarkSchemes copy() { + return new DemonOfDarkSchemes(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/DovinBaan.java b/Mage.Sets/src/mage/sets/kaladesh/DovinBaan.java new file mode 100644 index 0000000000..959b559c5f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/DovinBaan.java @@ -0,0 +1,159 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.RestrictionUntapNotMoreThanEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class DovinBaan extends CardImpl { + + public DovinBaan(UUID ownerId) { + super(ownerId, 179, "Dovin Baan", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{2}{W}{U}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dovin"); + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); + + // +1: Until your next turn, up to one target creature gets -3/-0 and its activated abilities can't be activated. + Effect effect = new BoostTargetEffect(-3, 0, Duration.UntilYourNextTurn); + effect.setText("Until your next turn, up to one target creature gets -3/-0"); + Ability ability = new LoyaltyAbility(effect, 1); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + ability.addEffect(new DovinBaanCantActivateAbilitiesEffect()); + this.addAbility(ability); + + // -1: You gain 2 life and draw a card. + ability = new LoyaltyAbility(new GainLifeEffect(2), -1); + effect = new DrawCardSourceControllerEffect(1); + effect.setText("and draw a card"); + ability.addEffect(effect); + this.addAbility(ability); + + // -7: You get an emblem with "Your opponents can't untap more than two permanents during their untap steps." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new DovinBaanEmblem()), -7)); + } + + public DovinBaan(final DovinBaan card) { + super(card); + } + + @Override + public DovinBaan copy() { + return new DovinBaan(this); + } +} + +class DovinBaanCantActivateAbilitiesEffect extends ContinuousRuleModifyingEffectImpl { + + DovinBaanCantActivateAbilitiesEffect() { + super(Duration.UntilYourNextTurn, Outcome.UnboostCreature); + staticText = "and its activated abilities can't be activated"; + } + + DovinBaanCantActivateAbilitiesEffect(final DovinBaanCantActivateAbilitiesEffect effect) { + super(effect); + } + + @Override + public DovinBaanCantActivateAbilitiesEffect copy() { + return new DovinBaanCantActivateAbilitiesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ACTIVATE_ABILITY; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getSourceId().equals(this.getTargetPointer().getFirst(game, source)); + } +} + +class DovinBaanEmblem extends Emblem { + + DovinBaanEmblem() { + this.setName("EMBLEM: Dovin Baan"); + Ability ability = new SimpleStaticAbility(Zone.COMMAND, new DovinBaanCantUntapEffect()); + this.getAbilities().add(ability); + } +} + +class DovinBaanCantUntapEffect extends RestrictionUntapNotMoreThanEffect { + + DovinBaanCantUntapEffect() { + super(Duration.WhileOnBattlefield, 2, new FilterControlledPermanent()); + staticText = "Your opponents can't untap more than two permanents during their untap steps."; + } + + DovinBaanCantUntapEffect(final DovinBaanCantUntapEffect effect) { + super(effect); + } + + @Override + public boolean applies(Player player, Ability source, Game game) { + return game.getOpponents(source.getControllerId()).contains(player.getId()); + } + + @Override + public DovinBaanCantUntapEffect copy() { + return new DovinBaanCantUntapEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ElectrostaticPummeler.java b/Mage.Sets/src/mage/sets/kaladesh/ElectrostaticPummeler.java new file mode 100644 index 0000000000..ef3fba62e6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ElectrostaticPummeler.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author emerald000 + */ +public class ElectrostaticPummeler extends CardImpl { + + public ElectrostaticPummeler(UUID ownerId) { + super(ownerId, 210, "Electrostatic Pummeler", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Electrostatic Pummeler enters the battlefield, you get {E}{E}{E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(3))); + + // Pay {E}{E}{E}: Electrostatic Pummeler gets +X/+X until end of turn, where X is its power. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(new SourcePermanentPowerCount(), new SourcePermanentPowerCount(), Duration.EndOfTurn, true), new PayEnergyCost(3))); + } + + public ElectrostaticPummeler(final ElectrostaticPummeler card) { + super(card); + } + + @Override + public ElectrostaticPummeler copy() { + return new ElectrostaticPummeler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/EssenceExtraction.java b/Mage.Sets/src/mage/sets/kaladesh/EssenceExtraction.java new file mode 100644 index 0000000000..ff3370418e --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/EssenceExtraction.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class EssenceExtraction extends CardImpl { + + public EssenceExtraction(UUID ownerId) { + super(ownerId, 80, "Essence Extraction", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{B}{B}"); + this.expansionSetCode = "KLD"; + + // Essence Extraction deals 3 damage to target creature and you gain 3 life. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + Effect effect = new DamageTargetEffect(3); + effect.setText("{this} deals 3 damage to target creature"); + this.getSpellAbility().addEffect(effect); + effect = new GainLifeEffect(3); + effect.setText("and you gain 3 life"); + this.getSpellAbility().addEffect(effect); + } + + public EssenceExtraction(final EssenceExtraction card) { + super(card); + } + + @Override + public EssenceExtraction copy() { + return new EssenceExtraction(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/InspiredCharge.java b/Mage.Sets/src/mage/sets/kaladesh/InspiredCharge.java new file mode 100644 index 0000000000..6ddfb3f7b0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/InspiredCharge.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class InspiredCharge extends mage.sets.magic2011.InspiredCharge { + + public InspiredCharge(UUID ownerId) { + super(ownerId); + this.cardNumber = "20"; + this.expansionSetCode = "KLD"; + } + + public InspiredCharge(final InspiredCharge card) { + super(card); + } + + @Override + public InspiredCharge copy() { + return new InspiredCharge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/LiveFast.java b/Mage.Sets/src/mage/sets/kaladesh/LiveFast.java new file mode 100644 index 0000000000..00588dc39f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/LiveFast.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class LiveFast extends CardImpl { + + public LiveFast(UUID ownerId) { + super(ownerId, 87, "Live Fast", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); + this.expansionSetCode = "KLD"; + + // You draw two cards, lose 2 life, and get {E}{E}. + Effect effect = new DrawCardSourceControllerEffect(2); + effect.setText("You draw two cards"); + getSpellAbility().addEffect(effect); + effect = new LoseLifeSourceControllerEffect(2); + effect.setText(", lose 2 life"); + getSpellAbility().addEffect(effect); + effect = new GetEnergyCountersControllerEffect(2); + effect.setText(", and get {E}{E} (two energy counters)."); + getSpellAbility().addEffect(effect); + } + + public LiveFast(final LiveFast card) { + super(card); + } + + @Override + public LiveFast copy() { + return new LiveFast(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/MaulfistSquad.java b/Mage.Sets/src/mage/sets/kaladesh/MaulfistSquad.java new file mode 100644 index 0000000000..abe8fd248e --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/MaulfistSquad.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.FabricateAbility; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class MaulfistSquad extends CardImpl { + + public MaulfistSquad(UUID ownerId) { + super(ownerId, 91, "Maulfist Squad", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Human"); + this.subtype.add("Artificer"); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Menace + this.addAbility(new MenaceAbility()); + + // Fabricate 1 + this.addAbility(new FabricateAbility(1)); + } + + public MaulfistSquad(final MaulfistSquad card) { + super(card); + } + + @Override + public MaulfistSquad copy() { + return new MaulfistSquad(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/NoxiousGearhulk.java b/Mage.Sets/src/mage/sets/kaladesh/NoxiousGearhulk.java new file mode 100644 index 0000000000..76f79f68d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/NoxiousGearhulk.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class NoxiousGearhulk extends CardImpl { + + public NoxiousGearhulk(UUID ownerId) { + super(ownerId, 96, "Noxious Gearhulk", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{B}{B}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Menace + this.addAbility(new MenaceAbility()); + + // When Noxious Gearhulk enters the battlefield, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness. + Ability ability = new EntersBattlefieldTriggeredAbility(new NoxiousGearhulkEffect()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public NoxiousGearhulk(final NoxiousGearhulk card) { + super(card); + } + + @Override + public NoxiousGearhulk copy() { + return new NoxiousGearhulk(this); + } +} + +class NoxiousGearhulkEffect extends OneShotEffect { + + public NoxiousGearhulkEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness"; + } + + public NoxiousGearhulkEffect(final NoxiousGearhulkEffect effect) { + super(effect); + } + + @Override + public NoxiousGearhulkEffect copy() { + return new NoxiousGearhulkEffect(this); + } + + @Override + public boolean apply(Game game, final Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent creatureToDestroy = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (creatureToDestroy != null && player != null) { + if (player.chooseUse(Outcome.DestroyPermanent, "Destroy creature?", source, game)) { + if (creatureToDestroy.destroy(source.getSourceId(), game, false)) { + player.gainLife(creatureToDestroy.getToughness().getValue(), game); + } + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/PropheticPrism.java b/Mage.Sets/src/mage/sets/kaladesh/PropheticPrism.java new file mode 100644 index 0000000000..bac6de5dbe --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/PropheticPrism.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class PropheticPrism extends mage.sets.riseoftheeldrazi.PropheticPrism { + + public PropheticPrism(UUID ownerId) { + super(ownerId); + this.cardNumber = "229"; + this.expansionSetCode = "KLD"; + } + + public PropheticPrism(final PropheticPrism card) { + super(card); + } + + @Override + public PropheticPrism copy() { + return new PropheticPrism(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ScrapheapScrounger.java b/Mage.Sets/src/mage/sets/kaladesh/ScrapheapScrounger.java new file mode 100644 index 0000000000..698fed25bd --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ScrapheapScrounger.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.CantBlockAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileFromGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.AnotherCardPredicate; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author emerald000 + */ +public class ScrapheapScrounger extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("another creature card"); + static { + filter.add(new AnotherCardPredicate()); + } + + public ScrapheapScrounger(UUID ownerId) { + super(ownerId, 231, "Scrapheap Scrounger", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Scrapheap Scrounger can't block. + this.addAbility(new CantBlockAbility()); + + // {1}{B}, Exile another creature card from your graveyard: Return Scrapheap Scrounger from your graveyard to the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false), new ManaCostsImpl<>("{1}{B}")); + ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(filter))); + this.addAbility(ability); + } + + public ScrapheapScrounger(final ScrapheapScrounger card) { + super(card); + } + + @Override + public ScrapheapScrounger copy() { + return new ScrapheapScrounger(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/SpeedwayFanatic.java b/Mage.Sets/src/mage/sets/kaladesh/SpeedwayFanatic.java new file mode 100644 index 0000000000..9ee0b872b0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/SpeedwayFanatic.java @@ -0,0 +1,113 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class SpeedwayFanatic extends CardImpl { + + public SpeedwayFanatic(UUID ownerId) { + super(ownerId, 132, "Speedway Fanatic", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Human"); + this.subtype.add("Pilot"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Speedway Fanatic crews a Vehicle, that Vehicle gains haste until end of turn. + this.addAbility(new CrewsVehicleSourceTriggeredAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn, + "that Vehicle gains haste until end of turn"))); + } + + public SpeedwayFanatic(final SpeedwayFanatic card) { + super(card); + } + + @Override + public SpeedwayFanatic copy() { + return new SpeedwayFanatic(this); + } +} + +class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl { + + public CrewsVehicleSourceTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect, false); + } + + public CrewsVehicleSourceTriggeredAbility(final CrewsVehicleSourceTriggeredAbility ability) { + super(ability); + } + + @Override + public CrewsVehicleSourceTriggeredAbility copy() { + return new CrewsVehicleSourceTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CREWED_VEHICLE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getTargetId().equals(getSourceId())) { + for (Effect effect : getEffects()) { + // set the vehicle id as target + effect.setTargetPointer(new FixedTarget(event.getSourceId())); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "When {this} crews a Vehicle, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/StoneQuarry.java b/Mage.Sets/src/mage/sets/kaladesh/StoneQuarry.java new file mode 100644 index 0000000000..accb7be62f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/StoneQuarry.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class StoneQuarry extends mage.sets.shadowsoverinnistrad.StoneQuarry { + + public StoneQuarry(UUID ownerId) { + super(ownerId); + this.cardNumber = "269"; + this.expansionSetCode = "KLD"; + this.rarity = Rarity.COMMON; + } + + public StoneQuarry(final StoneQuarry card) { + super(card); + } + + @Override + public StoneQuarry copy() { + return new StoneQuarry(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ThrivingRats.java b/Mage.Sets/src/mage/sets/kaladesh/ThrivingRats.java new file mode 100644 index 0000000000..7a7769950c --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ThrivingRats.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; + +/** + * + * @author fireshoes + */ +public class ThrivingRats extends CardImpl { + + public ThrivingRats(UUID ownerId) { + super(ownerId, 102, "Thriving Rats", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Rat"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // When Thriving Rats enters the battlefield, you get {E}{E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(2))); + + // Whenever Thriving Rats attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it. + this.addAbility(new AttacksTriggeredAbility(new DoIfCostPaid(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new PayEnergyCost(2)), false, + "Whenever {this} attacks you may pay {E}{E}. If you do, put a +1/+1 counter on it.")); + } + + public ThrivingRats(final ThrivingRats card) { + super(card); + } + + @Override + public ThrivingRats copy() { + return new ThrivingRats(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/UnderhandedDesigns.java b/Mage.Sets/src/mage/sets/kaladesh/UnderhandedDesigns.java new file mode 100644 index 0000000000..2fa780ec15 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/UnderhandedDesigns.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition.CountType; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class UnderhandedDesigns extends CardImpl { + + public UnderhandedDesigns(UUID ownerId) { + super(ownerId, 104, "Underhanded Designs", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + this.expansionSetCode = "KLD"; + + // Whenever an artifact enters the battlefield under your control, you may pay {1}. If you do, each opponent loses 1 life and you gain 1 life. + DoIfCostPaid doIfCostPaid = new DoIfCostPaid(new LoseLifeOpponentsEffect(1), new GenericManaCost(1)); + Effect effect = new GainLifeEffect(1); + doIfCostPaid.addEffect(effect); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, doIfCostPaid, new FilterControlledArtifactPermanent("an artifact"), false, + "Whenever an artifact enters the battlefield under your control, you may pay {1}. If you do, each opponent loses 1 life and you gain 1 life.")); + + // {1}{B}, Sacrifice Underhanded Designs: Destroy target creature. Activate this ability only if you control two or more artifacts. + Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, + new DestroyTargetEffect(), + new ManaCostsImpl("{1}{B}"), + new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent("you control two or more artifacts"), CountType.MORE_THAN, 1)); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public UnderhandedDesigns(final UnderhandedDesigns card) { + super(card); + } + + @Override + public UnderhandedDesigns copy() { + return new UnderhandedDesigns(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/WhirlerVirtuoso.java b/Mage.Sets/src/mage/sets/kaladesh/WhirlerVirtuoso.java new file mode 100644 index 0000000000..1cc8c66cbd --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/WhirlerVirtuoso.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.permanent.token.ThopterColorlessToken; + +/** + * + * @author emerald000 + */ +public class WhirlerVirtuoso extends CardImpl { + + public WhirlerVirtuoso(UUID ownerId) { + super(ownerId, 190, "Whirler Virtuoso", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vedalken"); + this.subtype.add("Artificer"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // When Whirler Virtuoso enters the battlefield, you get {E}{E}{E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(3))); + + // Pay {E}{E}{E}: Create a 1/1 colorless Thopter artifact creature token with flying. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken()), new PayEnergyCost(3))); + } + + public WhirlerVirtuoso(final WhirlerVirtuoso card) { + super(card); + } + + @Override + public WhirlerVirtuoso copy() { + return new WhirlerVirtuoso(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/WoodlandStream.java b/Mage.Sets/src/mage/sets/kaladesh/WoodlandStream.java new file mode 100644 index 0000000000..2e68921e59 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/WoodlandStream.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class WoodlandStream extends mage.sets.shadowsoverinnistrad.WoodlandStream { + + public WoodlandStream(UUID ownerId) { + super(ownerId); + this.cardNumber = "274"; + this.expansionSetCode = "KLD"; + this.rarity = Rarity.COMMON; + } + + public WoodlandStream(final WoodlandStream card) { + super(card); + } + + @Override + public WoodlandStream copy() { + return new WoodlandStream(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/DingusEgg.java b/Mage.Sets/src/mage/sets/limitedalpha/DingusEgg.java index 0c197a4e18..69a87caf95 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/DingusEgg.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/DingusEgg.java @@ -86,7 +86,7 @@ class DingusEggTriggeredAbility extends TriggeredAbilityImpl { if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getTarget().getCardType().contains(CardType.LAND)) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { UUID targetId = zEvent.getTarget().getControllerId(); for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(targetId)); diff --git a/Mage.Sets/src/mage/sets/masterpieceseries/NoxiousGearhulk.java b/Mage.Sets/src/mage/sets/masterpieceseries/NoxiousGearhulk.java new file mode 100644 index 0000000000..2bd02fe7dc --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterpieceseries/NoxiousGearhulk.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterpieceseries; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class NoxiousGearhulk extends mage.sets.kaladesh.NoxiousGearhulk { + + public NoxiousGearhulk(UUID ownerId) { + super(ownerId); + this.cardNumber = "3"; + this.expansionSetCode = "MPS"; + } + + public NoxiousGearhulk(final NoxiousGearhulk card) { + super(card); + } + + @Override + public NoxiousGearhulk copy() { + return new NoxiousGearhulk(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/KnowledgePool.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/KnowledgePool.java index 8e5c3114ca..1d587e3dc8 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/KnowledgePool.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/KnowledgePool.java @@ -178,7 +178,6 @@ class KnowledgePoolEffect2 extends OneShotEffect { while (player.choose(Outcome.PlayForFree, game.getExile().getExileZone(exileZoneId), target, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null && !card.getId().equals(spell.getSourceId())) { - game.getExile().removeCard(card, game); return player.cast(card.getSpellAbility(), game, true); } target.clearChosen(); diff --git a/Mage.Sets/src/mage/sets/odyssey/GorillaTitan.java b/Mage.Sets/src/mage/sets/odyssey/GorillaTitan.java index 401c7969f8..0d07fca333 100644 --- a/Mage.Sets/src/mage/sets/odyssey/GorillaTitan.java +++ b/Mage.Sets/src/mage/sets/odyssey/GorillaTitan.java @@ -84,7 +84,7 @@ class GorillaTitanCondition implements Condition { Player p = game.getPlayer(source.getControllerId()); if (p != null) { - return p.getGraveyard().size() == 0; + return p.getGraveyard().isEmpty(); } return false; } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/CloneShell.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/CloneShell.java index 850aa23754..52bd1e5a22 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/CloneShell.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/CloneShell.java @@ -102,7 +102,7 @@ class CloneShellEffect extends OneShotEffect { cards.add(card); } - if (cards.size() == 0) { + if (cards.isEmpty()) { return false; } diff --git a/Mage.Sets/src/mage/sets/seventhedition/AEtherFlash.java b/Mage.Sets/src/mage/sets/seventhedition/AEtherFlash.java index ea9bcd7ade..1e40e6aab3 100644 --- a/Mage.Sets/src/mage/sets/seventhedition/AEtherFlash.java +++ b/Mage.Sets/src/mage/sets/seventhedition/AEtherFlash.java @@ -89,7 +89,7 @@ class AEtherFlashTriggeredAbility extends TriggeredAbilityImpl { UUID targetId = event.getTargetId(); Permanent permanent = game.getPermanent(targetId); if (filter.match(permanent, getSourceId(), getControllerId(), game)) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(targetId)); } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/HollowbornBarghest.java b/Mage.Sets/src/mage/sets/shadowmoor/HollowbornBarghest.java index 593dcdc149..dcb6c8486c 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/HollowbornBarghest.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/HollowbornBarghest.java @@ -134,7 +134,7 @@ class HollowbornBarghestTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(controllerId).contains(event.getPlayerId())) { Player opponent = game.getPlayer(event.getPlayerId()); - if (opponent != null && opponent.getHand().size() == 0) { + if (opponent != null && opponent.getHand().isEmpty()) { opponent.loseLife(2, game); return true; } diff --git a/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java b/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java index 60ff87f1b9..2d9c085ee3 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java @@ -100,7 +100,7 @@ class ImmortalCoilAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { Player player = game.getPlayer(this.getControllerId()); - return player != null && player.getGraveyard().size() == 0; + return player != null && player.getGraveyard().isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/sets/urzaslegacy/Rivalry.java b/Mage.Sets/src/mage/sets/urzaslegacy/Rivalry.java index 4b79443702..1f516789ff 100644 --- a/Mage.Sets/src/mage/sets/urzaslegacy/Rivalry.java +++ b/Mage.Sets/src/mage/sets/urzaslegacy/Rivalry.java @@ -94,7 +94,7 @@ class RivalryTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage.Sets/src/mage/sets/worldwake/QuestForTheNihilStone.java b/Mage.Sets/src/mage/sets/worldwake/QuestForTheNihilStone.java index 65f6c15be9..82d39a99f8 100644 --- a/Mage.Sets/src/mage/sets/worldwake/QuestForTheNihilStone.java +++ b/Mage.Sets/src/mage/sets/worldwake/QuestForTheNihilStone.java @@ -133,7 +133,7 @@ class QuestForTheNihilStoneTriggeredAbility2 extends TriggeredAbilityImpl { if (game.getOpponents(controllerId).contains(event.getPlayerId())) { Player opponent = game.getPlayer(event.getPlayerId()); if (opponent != null - && opponent.getHand().size() == 0 + && opponent.getHand().isEmpty() && quest.getCounters(game).getCount(CounterType.QUEST) >= 2) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(opponent.getId())); diff --git a/Mage.Sets/src/mage/sets/worldwake/Terastodon.java b/Mage.Sets/src/mage/sets/worldwake/Terastodon.java index 2eeb984a43..ad2eb45ae7 100644 --- a/Mage.Sets/src/mage/sets/worldwake/Terastodon.java +++ b/Mage.Sets/src/mage/sets/worldwake/Terastodon.java @@ -27,6 +27,8 @@ */ package mage.sets.worldwake; +import java.util.HashMap; +import java.util.Map.Entry; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; @@ -43,7 +45,6 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.ElephantToken; -import mage.players.Player; import mage.target.TargetPermanent; /** @@ -100,18 +101,25 @@ class TerastodonEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + HashMap destroyedPermanents = new HashMap<>(); for (UUID targetID : this.targetPointer.getTargets(game, source)) { Permanent permanent = game.getPermanent(targetID); if (permanent != null) { if (permanent.destroy(source.getSourceId(), game, false)) { if (game.getState().getZone(permanent.getId()) == Zone.GRAVEYARD) { - Player controller = game.getPlayer(permanent.getControllerId()); - ElephantToken elephantToken = new ElephantToken(); - elephantToken.putOntoBattlefield(1, game, source.getSourceId(), controller.getId()); + int numberPermanents = 0; + if (destroyedPermanents.containsKey(permanent.getControllerId())) { + numberPermanents = destroyedPermanents.get(permanent.getControllerId()); + } + destroyedPermanents.put(permanent.getControllerId(), numberPermanents); } } } } + ElephantToken elephantToken = new ElephantToken(); + for (Entry entry : destroyedPermanents.entrySet()) { + elephantToken.putOntoBattlefield(entry.getValue(), game, source.getSourceId(), entry.getKey()); + } return true; } } diff --git a/Mage.Sets/src/mage/sets/zendikar/GuulDrazSpecter.java b/Mage.Sets/src/mage/sets/zendikar/GuulDrazSpecter.java index 807449dbe7..20e512807c 100644 --- a/Mage.Sets/src/mage/sets/zendikar/GuulDrazSpecter.java +++ b/Mage.Sets/src/mage/sets/zendikar/GuulDrazSpecter.java @@ -90,7 +90,7 @@ class GuulDrazSpecterCondition implements Condition { Set opponents = game.getOpponents(source.getControllerId()); for (UUID opponentId : opponents) { - result |= game.getPlayer(opponentId).getHand().size() == 0; + result |= game.getPlayer(opponentId).getHand().isEmpty(); } return result; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CrewTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CrewTest.java new file mode 100644 index 0000000000..74c545302e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CrewTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * 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.abilities.keyword.HasteAbility; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +// http://magic.wizards.com/en/articles/archive/feature/kaladesh-mechanics-2016-09-02 +public class CrewTest extends CardTestPlayerBase { + + @Test + public void crewBasicTest() { + // {T}: Add one mana of any color to your mana pool. + // 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.)"; + addCard(Zone.BATTLEFIELD, playerA, "Cultivator's Caravan", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 2); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crew 3"); + setChoice(playerA, "Silvercoat Lion^Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertTappedCount("Silvercoat Lion", true, 2); + assertPowerToughness(playerA, "Cultivator's Caravan", 5, 5); + assertType("Cultivator's Caravan", CardType.CREATURE, "Vehicle"); + } + + @Test + public void crewTriggerPilotTest() { + // Flying + // Whenever Smuggler's Copter attacks or blocks, you may draw a card. If you do, discard a card. + // Crew 1 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)"; + addCard(Zone.BATTLEFIELD, playerA, "Smuggler's Copter", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Speedway Fanatic", 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crew 1"); + setChoice(playerA, "Speedway Fanatic"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertTappedCount("Speedway Fanatic", true, 1); + assertPowerToughness(playerA, "Smuggler's Copter", 3, 3); + assertAbility(playerA, "Smuggler's Copter", HasteAbility.getInstance(), true); + assertType("Smuggler's Copter", CardType.CREATURE, "Vehicle"); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/BaneOfProgessTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/BaneOfProgessTest.java new file mode 100644 index 0000000000..221325d4ab --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/BaneOfProgessTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * 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.oneshot.destroy; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class BaneOfProgessTest extends CardTestPlayerBase { + + @Test + public void testDestroy() { + // You may play land cards from your graveyard. + addCard(Zone.BATTLEFIELD, playerA, "Crucible of Worlds"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + // Put a token onto the battlefield that's a copy of target artifact or creature. + // Cipher (Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost.) + addCard(Zone.HAND, playerA, "Stolen Identity"); // {4}{U}{U} + + addCard(Zone.BATTLEFIELD, playerB, "Forest", 6); + // When Bane of Progress enters the battlefield, destroy all artifacts and enchantments. Put a +1/+1 counter on Bane of Progress for each permanent destroyed this way. + addCard(Zone.HAND, playerB, "Bane of Progress"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stolen Identity", "Crucible of Worlds"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Bane of Progress"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Stolen Identity", 1); + assertPermanentCount(playerA, "Crucible of Worlds", 0); + + assertPermanentCount(playerB, "Bane of Progress", 1); + assertPowerToughness(playerB, "Bane of Progress", 4, 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/EchoingTruthTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/EchoingTruthTest.java new file mode 100644 index 0000000000..aecfb406e7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/EchoingTruthTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.single; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EchoingTruthTest extends CardTestPlayerBase { + + /** + * I played "Echoing Truth" targeting one of my opponent's spirit tokens + * from Spectral Processions and NONE OF THEM got bounced. + */ + @Test + public void testReturnTokens() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.HAND, playerA, "Spectral Procession"); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + addCard(Zone.HAND, playerB, "Echoing Truth"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spectral Procession"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Echoing Truth", "Spirit"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertGraveyardCount(playerA, "Spectral Procession", 1); + assertGraveyardCount(playerB, "Echoing Truth", 1); + assertPermanentCount(playerA, "Spirit", 0); + + } + +} diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java index 873c67d7b4..76baa6b650 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java @@ -45,7 +45,7 @@ public class BeginningOfCombatTriggeredAbility extends TriggeredAbilityImpl { case YOU: boolean yours = event.getPlayerId().equals(this.controllerId); if (yours && setTargetPointer) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java index acb46c71a8..34b7a0af99 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java @@ -77,7 +77,7 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl { case YOU: boolean yours = event.getPlayerId().equals(this.controllerId); if (yours) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } @@ -86,7 +86,7 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl { return yours; case OPPONENT: if (game.getPlayer(this.controllerId).hasOpponent(event.getPlayerId(), game)) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } @@ -96,7 +96,7 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl { break; case NOT_YOU: if (!this.controllerId.equals(event.getPlayerId())) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } @@ -109,7 +109,7 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl { if (attachment != null && attachment.getAttachedTo() != null) { Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); if (attachedTo != null && attachedTo.getControllerId().equals(event.getPlayerId())) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } @@ -119,7 +119,7 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl { } break; case ANY: - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfPreCombatMainTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfPreCombatMainTriggeredAbility.java index 1460e31ccf..207f9b9bf1 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfPreCombatMainTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfPreCombatMainTriggeredAbility.java @@ -54,7 +54,7 @@ public class BeginningOfPreCombatMainTriggeredAbility extends TriggeredAbilityIm case YOU: boolean yours = event.getPlayerId().equals(this.controllerId); if (yours && setTargetPointer) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfUntapTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfUntapTriggeredAbility.java index 35d68b69c0..bc685c9fa7 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfUntapTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfUntapTriggeredAbility.java @@ -71,7 +71,7 @@ public class BeginningOfUntapTriggeredAbility extends TriggeredAbilityImpl { break; case OPPONENT: if (game.getPlayer(this.controllerId).hasOpponent(event.getPlayerId(), game)) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } @@ -82,7 +82,7 @@ public class BeginningOfUntapTriggeredAbility extends TriggeredAbilityImpl { case ANY: controller = game.getPlayer(this.getControllerId()); if (controller != null && controller.getInRange().contains(event.getPlayerId())) { - if (getTargets().size() == 0) { + if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage/src/main/java/mage/abilities/condition/common/HellbentCondition.java b/Mage/src/main/java/mage/abilities/condition/common/HellbentCondition.java index d65031ad88..fb2f226684 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/HellbentCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/HellbentCondition.java @@ -41,7 +41,7 @@ public class HellbentCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return game.getPlayer(source.getControllerId()).getHand().size() == 0; + return game.getPlayer(source.getControllerId()).getHand().isEmpty(); } @Override diff --git a/Mage/src/main/java/mage/abilities/costs/CostsImpl.java b/Mage/src/main/java/mage/abilities/costs/CostsImpl.java index 2d070ac91a..f17c7b9b2f 100644 --- a/Mage/src/main/java/mage/abilities/costs/CostsImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/CostsImpl.java @@ -70,7 +70,7 @@ public class CostsImpl extends ArrayList implements Costs if (text != null) { return text; } - if (this.size() == 0) { + if (this.isEmpty()) { return ""; } diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java index 9d9b89d874..2d14c311a7 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java @@ -262,11 +262,11 @@ public class ManaCostsImpl extends ArrayList implements M // First try only to pay colored mana with the pool for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof MonoHybridManaCost) { - if (((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.W)) && pool.getWhite() > 0) - || ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.B)) && pool.getBlack() > 0) - || ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.R)) && pool.getRed() > 0) - || ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.G)) && pool.getGreen() > 0) - || ((((MonoHybridManaCost) cost).containsColor(ColoredManaSymbol.U)) && pool.getBlue() > 0)) { + if (((cost.containsColor(ColoredManaSymbol.W)) && pool.getWhite() > 0) + || ((cost.containsColor(ColoredManaSymbol.B)) && pool.getBlack() > 0) + || ((cost.containsColor(ColoredManaSymbol.R)) && pool.getRed() > 0) + || ((cost.containsColor(ColoredManaSymbol.G)) && pool.getGreen() > 0) + || ((cost.containsColor(ColoredManaSymbol.U)) && pool.getBlue() > 0)) { cost.assignPayment(game, ability, pool, costToPay); if (pool.count() == 0) { return; @@ -315,12 +315,12 @@ public class ManaCostsImpl extends ArrayList implements M public final void load(String mana) { this.clear(); if (costs.containsKey(mana)) { - ManaCosts savedCosts = costs.get(mana); + ManaCosts savedCosts = costs.get(mana); for (ManaCost cost : savedCosts) { - this.add((T) cost.copy()); + this.add(cost.copy()); } } else { - if (mana == null || mana.length() == 0) { + if (mana == null || mana.isEmpty()) { return; } String[] symbols = mana.split("^\\{|\\}\\{|\\}$"); @@ -347,11 +347,11 @@ public class ManaCostsImpl extends ArrayList implements M this.add(new VariableManaCost(modifierForX)); } //TODO: handle multiple {X} and/or {Y} symbols } else if (Character.isDigit(symbol.charAt(0))) { - this.add((T) new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2)))); + this.add(new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2)))); } else if (symbol.contains("P")) { - this.add((T) new PhyrexianManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)))); + this.add(new PhyrexianManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)))); } else { - this.add((T) new HybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)), ColoredManaSymbol.lookup(symbol.charAt(2)))); + this.add(new HybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)), ColoredManaSymbol.lookup(symbol.charAt(2)))); } } } @@ -392,7 +392,7 @@ public class ManaCostsImpl extends ArrayList implements M if (text != null) { return text; } - if (this.size() == 0) { + if (this.isEmpty()) { return ""; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java index 51ea80d664..a409e5b1fd 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java @@ -110,7 +110,7 @@ public class CounterUnlessPaysEffect extends OneShotEffect { } StringBuilder sb = new StringBuilder(); - if (mode.getTargets().size() == 0) { + if (mode.getTargets().isEmpty()) { sb.append("counter it"); } else { sb.append("Counter target ").append(mode.getTargets().get(0).getTargetName()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageFromChosenSourceToYouEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageFromChosenSourceToYouEffect.java new file mode 100644 index 0000000000..c8e40bd480 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageFromChosenSourceToYouEffect.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.FilterObject; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.TargetSource; + +/** + * + * @author LevelX2 + */ +public class PreventAllDamageFromChosenSourceToYouEffect extends PreventionEffectImpl { + + protected final TargetSource targetSource; + + public PreventAllDamageFromChosenSourceToYouEffect(Duration duration) { + this(duration, new FilterObject("source")); + } + + public PreventAllDamageFromChosenSourceToYouEffect(Duration duration, FilterObject filter) { + this(duration, filter, false); + } + + public PreventAllDamageFromChosenSourceToYouEffect(Duration duration, FilterObject filter, boolean onlyCombat) { + super(duration, Integer.MAX_VALUE, onlyCombat); + this.targetSource = new TargetSource(filter); + this.staticText = setText(); + } + + public PreventAllDamageFromChosenSourceToYouEffect(final PreventAllDamageFromChosenSourceToYouEffect effect) { + super(effect); + this.targetSource = effect.targetSource.copy(); + } + + @Override + public PreventAllDamageFromChosenSourceToYouEffect copy() { + return new PreventAllDamageFromChosenSourceToYouEffect(this); + } + + @Override + public void init(Ability source, Game game) { + this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + preventDamageAction(event, source, game); + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + if (event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(targetSource.getFirstTarget())) { + return true; + } + } + return false; + } + + private String setText() { + StringBuilder sb = new StringBuilder("Prevent all "); + if (onlyCombat) { + sb.append("combat "); + } + sb.append("damage that would be dealt to you "); + if (duration.equals(Duration.EndOfTurn)) { + sb.append("this turn "); + } + sb.append("by a ").append(targetSource.getFilter().getMessage()); + sb.append(" of your choice"); + return sb.toString(); + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java index faa2598939..1978154c16 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java @@ -1,77 +1,77 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.abilities.effects.common.counter; - -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.counters.CounterType; -import mage.game.Game; -import mage.players.Player; -import mage.util.CardUtil; - -/** - * @author emerald000 - */ -public class GetEnergyCountersControllerEffect extends OneShotEffect { - - private final int value; - - public GetEnergyCountersControllerEffect(int value) { - super(Outcome.Benefit); - this.value = value; - setText(); - } - - public GetEnergyCountersControllerEffect(final GetEnergyCountersControllerEffect effect) { - super(effect); - this.value = effect.value; - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - return player.addCounters(CounterType.ENERGY.createInstance(value), game); - } - return false; - } - - private void setText() { - this.staticText = "you get "; - for (int i = 0; i < value; i++) { - this.staticText += "{E}"; - } - this.staticText += " (" + CardUtil.numberToText(value, "an") + " energy counter" + (value > 1 ? "s" : "") + ")"; - } - - @Override - public GetEnergyCountersControllerEffect copy() { - return new GetEnergyCountersControllerEffect(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common.counter; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * @author emerald000 + */ +public class GetEnergyCountersControllerEffect extends OneShotEffect { + + private final int value; + + public GetEnergyCountersControllerEffect(int value) { + super(Outcome.Benefit); + this.value = value; + setText(); + } + + public GetEnergyCountersControllerEffect(final GetEnergyCountersControllerEffect effect) { + super(effect); + this.value = effect.value; + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + return player.addCounters(CounterType.ENERGY.createInstance(value), game); + } + return false; + } + + private void setText() { + this.staticText = "you get "; + for (int i = 0; i < value; i++) { + this.staticText += "{E}"; + } + this.staticText += " (" + CardUtil.numberToText(value, "an") + " energy counter" + (value > 1 ? "s" : "") + ")."; + } + + @Override + public GetEnergyCountersControllerEffect copy() { + return new GetEnergyCountersControllerEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java index 65215877da..d1f7c63fc4 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -41,6 +41,7 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; @@ -77,6 +78,7 @@ public class CrewAbility extends SimpleActivatedAbility { class CrewCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); + static { filter.add(Predicates.not(new TappedPredicate())); } @@ -104,6 +106,11 @@ class CrewCost extends CostImpl { } } paid = sumPower >= value; + if (paid) { + for (UUID targetId : target.getTargets()) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREWED_VEHICLE, targetId, sourceId, controllerId)); + } + } } return paid; } @@ -124,4 +131,4 @@ class CrewCost extends CostImpl { public CrewCost copy() { return new CrewCost(this); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/cards/CardsImpl.java b/Mage/src/main/java/mage/cards/CardsImpl.java index af2f3a2400..55123325f3 100644 --- a/Mage/src/main/java/mage/cards/CardsImpl.java +++ b/Mage/src/main/java/mage/cards/CardsImpl.java @@ -182,9 +182,13 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl @Override public Set getCards(Game game) { Set cards = new LinkedHashSet<>(); - for (Iterator it = this.iterator(); it.hasNext();) { // Changed to iterator becuase of ConcurrentModificationException + for (Iterator it = this.iterator(); it.hasNext();) { // Changed to iterator because of ConcurrentModificationException UUID cardId = it.next(); + Card card = game.getCard(cardId); + if (card == null) { + card = game.getPermanent(cardId); // needed to get TokenCard objects + } if (card != null) { // this can happen during the cancelation (player concedes) of a game cards.add(card); } diff --git a/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java index 24adc25b3d..800c3813fc 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java @@ -45,7 +45,7 @@ public class DckDeckImporter extends DeckImporter { @Override protected void readLine(String line, DeckCardLists deckList) { - if (line.length() == 0 || line.startsWith("#")) { + if (line.isEmpty() || line.startsWith("#")) { return; } diff --git a/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java index b1b095cf60..0dee3e9980 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java @@ -40,7 +40,7 @@ public class DecDeckImporter extends DeckImporter { @Override protected void readLine(String line, DeckCardLists deckList) { - if (line.length() == 0 || line.startsWith("//")) { + if (line.isEmpty() || line.startsWith("//")) { return; } diff --git a/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java index 885b569210..f66158ff34 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java @@ -13,7 +13,7 @@ public class DekDeckImporter extends DeckImporter { @Override protected void readLine(String line, DeckCardLists deckList) { - if (line.length() == 0 || line.startsWith("#") || !line.contains(" 0) { + if (line.isEmpty() && nonEmptyLinesTotal > 0) { sideboard = true; return; } else { diff --git a/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java b/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java index e175fc7fe4..11363f2eba 100644 --- a/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java +++ b/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java @@ -55,11 +55,11 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer @Override public boolean match(MageItem o, Game game) { if (o instanceof Player) { - if (((Player)o).getCounters().size() == 0) { + if (((Player)o).getCounters().isEmpty()) { return false; } } else if (o instanceof Permanent) { - if (((Permanent)o).getCounters(game).size() == 0) { + if (((Permanent)o).getCounters(game).isEmpty()) { return false; } } diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java index 27dc2b15b6..18959437de 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java @@ -46,6 +46,10 @@ public class AnotherTargetPredicate implements ObjectSourcePlayerPredicate 0 // target is included in the target group to check && target.getTargetTag() != targetTag // it's not the target of this predicate && target.getTargets().contains(input.getObject().getId())) { // if the uuid already is used for another target in the group it's not allowed here - return false; + return false; } } } diff --git a/Mage/src/main/java/mage/game/ZonesHandler.java b/Mage/src/main/java/mage/game/ZonesHandler.java index 4b1efae4c5..4d34f4b42b 100644 --- a/Mage/src/main/java/mage/game/ZonesHandler.java +++ b/Mage/src/main/java/mage/game/ZonesHandler.java @@ -1,5 +1,6 @@ package mage.game; +import java.util.*; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; @@ -16,12 +17,11 @@ import mage.game.stack.Spell; import mage.players.Player; import mage.target.TargetCard; -import java.util.*; - /** * Created by samuelsandeen on 9/6/16. */ public class ZonesHandler { + public static boolean cast(ZoneChangeInfo info, Game game) { if (maybeRemoveFromSourceZone(info, game)) { placeInDestinationZone(info, game); @@ -32,14 +32,14 @@ public class ZonesHandler { } public static boolean moveCard(ZoneChangeInfo info, Game game) { - List list = new ArrayList(); + List list = new ArrayList<>(); list.add(info); return moveCards(list, game).size() > 0; } public static List moveCards(List zoneChangeInfos, Game game) { // Handle Unmelded Meld Cards - for(ListIterator itr = zoneChangeInfos.listIterator(); itr.hasNext();) { + for (ListIterator itr = zoneChangeInfos.listIterator(); itr.hasNext();) { ZoneChangeInfo info = itr.next(); MeldCard card = game.getMeldCard(info.event.getTargetId()); // Copies should be handled as normal cards. @@ -170,12 +170,10 @@ public class ZonesHandler { ZoneChangeInfo subInfo = itr.next(); if (!maybeRemoveFromSourceZone(subInfo, game)) { itr.remove(); - } else { - if (subInfo.event.getTargetId() == meld.getTopHalfCard().getId()) { - meld.setTopLastZoneChangeCounter(meld.getTopHalfCard().getZoneChangeCounter(game)); - } else if (subInfo.event.getTargetId() == meld.getBottomHalfCard().getId()) { - meld.setBottomLastZoneChangeCounter(meld.getBottomHalfCard().getZoneChangeCounter(game)); - } + } else if (subInfo.event.getTargetId() == meld.getTopHalfCard().getId()) { + meld.setTopLastZoneChangeCounter(meld.getTopHalfCard().getZoneChangeCounter(game)); + } else if (subInfo.event.getTargetId() == meld.getBottomHalfCard().getId()) { + meld.setBottomLastZoneChangeCounter(meld.getBottomHalfCard().getZoneChangeCounter(game)); } } if (unmelded.subInfo.isEmpty()) { @@ -189,10 +187,13 @@ public class ZonesHandler { ZoneChangeEvent event = info.event; Card card = game.getCard(event.getTargetId()); boolean success = false; + if (card == null) { + return success; + } if (info.faceDown) { card.setFaceDown(true, game); } - if(!game.replaceEvent(event)) { + if (!game.replaceEvent(event)) { Zone fromZone = event.getFromZone(); if (event.getToZone() == Zone.BATTLEFIELD) { // controlling player can be replaced so use event player now @@ -246,7 +247,7 @@ public class ZonesHandler { } public static List chooseOrder(String message, Cards cards, Player player, Game game) { - List order = new ArrayList(); + List order = new ArrayList<>(); TargetCard target = new TargetCard(Zone.ALL, new FilterCard(message)); target.setRequired(true); while (player.isInGame() && cards.size() > 1) { diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index 8c6856acdc..aeda747014 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -97,7 +97,7 @@ public class GameEvent implements Serializable { CLASH, CLASHED, DAMAGE_PLAYER, /* DAMAGED_PLAYER - targetId the id of the damged player + targetId the id of the damaged player sourceId sourceId of the ability which caused the damage playerId the id of the damged player amount amount of damage @@ -109,6 +109,12 @@ public class GameEvent implements Serializable { GAIN_LIFE, GAINED_LIFE, LOSE_LIFE, LOST_LIFE, PLAY_LAND, LAND_PLAYED, + CREWED_VEHICLE, + /* CREWED_VEHICLE + targetId the id of the creature that crewed a vehicle + sourceId sourceId of the vehicle + playerId the id of the controlling player + */ CAST_SPELL, /* SPELL_CAST x-Costs are already defined diff --git a/Mage/src/main/java/mage/game/tournament/TournamentSwiss.java b/Mage/src/main/java/mage/game/tournament/TournamentSwiss.java index e755d47a6f..54337d71cc 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentSwiss.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentSwiss.java @@ -28,7 +28,7 @@ package mage.game.tournament; import java.util.List; -import java.util.Map; +import java.util.Map.Entry; import java.util.UUID; import mage.constants.TournamentPlayerState; @@ -49,7 +49,7 @@ public abstract class TournamentSwiss extends TournamentImpl { @Override protected void runTournament() { - for (Map.Entry entry : players.entrySet()) { + for (Entry entry : players.entrySet()) { if (entry.getValue().getPlayer().autoLoseGame()) { entry.getValue().setEliminated(); entry.getValue().setResults("Auto Eliminated"); diff --git a/Mage/src/main/java/mage/players/Library.java b/Mage/src/main/java/mage/players/Library.java index 73c258a4df..0723ef547d 100644 --- a/Mage/src/main/java/mage/players/Library.java +++ b/Mage/src/main/java/mage/players/Library.java @@ -38,13 +38,13 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.UUID; import mage.cards.Card; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; +import mage.util.RandomUtil; /** * @@ -52,7 +52,6 @@ import mage.game.Game; */ public class Library implements Serializable { - private static Random rnd = new Random(); private boolean emptyDraw; private final Deque library = new ArrayDeque<>(); private final UUID playerId; @@ -75,7 +74,7 @@ public class Library implements Serializable { public void shuffle() { UUID[] shuffled = library.toArray(new UUID[0]); for (int n = shuffled.length - 1; n > 0; n--) { - int r = rnd.nextInt(n); + int r = RandomUtil.nextInt(n);; UUID temp = shuffled[n]; shuffled[n] = shuffled[r]; shuffled[r] = temp; diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index 0fd3ebad7e..7ab223a4bc 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -474,4 +474,8 @@ public class ManaPool implements Serializable { } return false; } + + public boolean isEmpty(){ + return count() == 0; + } } diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 73dce6dae9..ecc11fbc66 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -40,7 +40,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; import java.util.Set; import java.util.UUID; import mage.ConditionalMana; @@ -83,7 +82,6 @@ import mage.actions.MageDrawAction; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; -import mage.cards.MeldCard; import mage.cards.SplitCard; import mage.cards.decks.Deck; import mage.constants.AbilityType; @@ -118,7 +116,6 @@ import mage.game.events.ZoneChangeEvent; import mage.game.match.MatchPlayer; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; -import mage.game.permanent.PermanentMeld; import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; @@ -1852,7 +1849,7 @@ public abstract class PlayerImpl implements Player, Serializable { returnCode = false; } } - if(finalAmount > 0) { + if (finalAmount > 0) { game.fireEvent(GameEvent.getEvent(EventType.COUNTERS_ADDED, playerId, playerId, counter.getName(), amount)); } } else { @@ -2536,7 +2533,7 @@ public abstract class PlayerImpl implements Player, Serializable { } } - if (manaCosts.size() == 0) { + if (manaCosts.isEmpty()) { return true; } else { if (available == null) { @@ -2567,7 +2564,7 @@ public abstract class PlayerImpl implements Player, Serializable { } } - if (manaCosts.size() == 0) { + if (manaCosts.isEmpty()) { return true; } else { for (Mana mana : manaCosts.getOptions()) { @@ -2604,7 +2601,7 @@ public abstract class PlayerImpl implements Player, Serializable { } } - if (manaCosts.size() == 0) { + if (manaCosts.isEmpty()) { return true; } else { for (Mana mana : manaCosts.getOptions()) { @@ -3161,9 +3158,9 @@ public abstract class PlayerImpl implements Player, Serializable { if (permanent != null) { successfulMovedCards.add(permanent); if (!game.isSimulation()) { - game.informPlayers(game.getPlayer(info.event.getPlayerId()) + " puts " + - (info.faceDown ? "a card face down " : permanent.getLogName()) + " from " + - fromZone.toString().toLowerCase(Locale.ENGLISH) + " onto the Battlefield"); + game.informPlayers(game.getPlayer(info.event.getPlayerId()) + " puts " + + (info.faceDown ? "a card face down " : permanent.getLogName()) + " from " + + fromZone.toString().toLowerCase(Locale.ENGLISH) + " onto the Battlefield"); } } } diff --git a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java index ae63a8aba9..c8f0497e31 100644 --- a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java +++ b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java @@ -80,13 +80,13 @@ public class TargetPermanentOrPlayerWithCounter extends TargetPermanentOrPlayer public boolean canTarget(UUID id, Game game) { Permanent permanent = game.getPermanent(id); if (permanent != null) { - if (permanent.getCounters(game).size() == 0) { + if (permanent.getCounters(game).isEmpty()) { return false; } } Player player = game.getPlayer(id); if (player != null) { - if (player.getCounters().size() == 0) { + if (player.getCounters().isEmpty()) { return false; } } @@ -97,13 +97,13 @@ public class TargetPermanentOrPlayerWithCounter extends TargetPermanentOrPlayer public boolean canTarget(UUID id, Ability source, Game game) { Permanent permanent = game.getPermanent(id); if (permanent != null) { - if (permanent.getCounters(game).size() == 0) { + if (permanent.getCounters(game).isEmpty()) { return false; } } Player player = game.getPlayer(id); if (player != null) { - if (player.getCounters().size() == 0) { + if (player.getCounters().isEmpty()) { return false; } } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 7c665b64cb..d746157578 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -78,7 +78,7 @@ public class CardUtil { // Enchantment subtypes "Aura", "Curse", "Shrine", // Artifact subtypes - "Clue", "Equipment", "Fortification", "Contraption", + "Clue", "Equipment", "Fortification", "Contraption", "Vehicle", // Land subtypes "Desert", "Gate", "Lair", "Locus", "Urza's", "Mine", "Power-Plant", "Tower", // Planeswalker subtypes diff --git a/Mage/src/main/java/mage/util/RandomUtil.java b/Mage/src/main/java/mage/util/RandomUtil.java index 3881b61e4a..e6ad582021 100644 --- a/Mage/src/main/java/mage/util/RandomUtil.java +++ b/Mage/src/main/java/mage/util/RandomUtil.java @@ -8,21 +8,18 @@ import java.util.concurrent.ThreadLocalRandom; */ public class RandomUtil { - private final static ThreadLocalRandom random = ThreadLocalRandom.current(); - public static Random getRandom() { - return random; - } + public static Random getRandom() {return ThreadLocalRandom.current();} public static int nextInt() { - return random.nextInt(); + return ThreadLocalRandom.current().nextInt(); } public static int nextInt(int max) { - return random.nextInt(max); + return ThreadLocalRandom.current().nextInt(max); } public static boolean nextBoolean() { - return random.nextBoolean(); + return ThreadLocalRandom.current().nextBoolean(); } } diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 8961dc69bc..8a0c72f754 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -29660,48 +29660,66 @@ Aerial Responder|Kaladesh|2|U|{1}{W}{W}|Creature - Dwarf Soldier|2|3|Flying, vig Aetherstorm Roc|Kaladesh|3|R|{2}{W}{W}|Creature - Bird|3|3|Flying$Whenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E} (an energy counter).$Whenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 creature on it and tap up to one target creature defending player controls.| Angel of Invention|Kaladesh|4|M|{3}{W}{W}|Creature - Angel|2|1|Flying, vigilance, lifelink$Fabricate 2 (When this creature enters the battlefield, put two +1/+1 counters on it or create two 1/1 colorless Servo artifact creature tokens.)$Other creatures you control get +1/+1.| Authority of the Consulate|Kaladesh|5|{W}|Enchantment|||Creatures your opponents control enter the battlefield tapped.$Whenever a creature enters the battlefield under an opponent's control, you gain 1 life.| +Aviary Mechanic|Kaladesh|6|C|{1}{W}|Creature - Dwarf Artificer|2|2|When Aviary Mechanic enters the battlefield, you may return another permanent you control to its owner's hand.| +Captured by the Consulate|Kaladesh|8|R|{3}{W}|Enchantment - Aura|||Enchant creature you don't control$Enchanted creature can't attack.$Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able.| Cataclysmic Gearhulk|Kaladesh|9|M|{3}{W}{W}|Artifact Creature - Construct|4|5|Vigilance$When Cataclysmic Gearhulk enters the battlefield, each player chooses from among the non-land permanents he or she controls an artifact, a creature, an enchantment, and a planeswalker, then sacrifices the rest.| Consulate Surveillance|Kaladesh|10|U|{3}{W}|Enchantment|||When Consulate Surveillance enters the battlefield, you get {E}{E}{E}{E} (four energy counters).$Pay {E}{E}: Prevent all damage that would be dealt to you this turn by a source of your choice.| Fragmentize|Kaladesh|14|C|{W}|Sorcery|||Destroy target artifact or enchantment with converted mana cost 4 or less.| Glint-Sleeve Artisan|Kaladesh|17|C|{2}{W}|Creature - Dwarf Artificer|2|2|Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Impeccable Timing|Kaladesh|19|C|{1}{W}|Instant|||Impeccable Timing deals 3 damage to target attacking or blocking creature.| Inspired Charge|Kaladesh|20|C|{2}{W}{W}|Instant|||Creatures you control get +2/+1 until end of turn.| Master Trinketcrafter|Kaladesh|21|R|{2}{W}|Creature - Dwarf Artificer|3|2|Servo and Thopter creatures you control get +1/+1.${3}{W}: Create a 1/1 colorless Servo artifact creature token.| Propeller Pioneer|Kaladesh|24|C|{3}{W}|Creature - Human Artificer|2|1|Flying$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Refurbish|Kaladesh|25|U|{3}{W}|Sorcery|||Return target artifact card from your graveyard to the battlefield.| +Skywhaler's Shot|Kaladesh|29|U|{2}{W}|Instant|||Destroy target creature with power 3 or greater. Scry 1.| Tasseled Dromedary|Kaladesh|30|C|{W}|Creature - Camel|0|4|| Thriving Ibex|Kaladesh|31|C|{3}{W}|Creature - Goat|2|4|When Thriving Ibex enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Ibex attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Toolcraft Exemplar|Kaladesh|32|R|{W}|Creature - Dwarf Artificer|1|1|At the beginning of your combat step, if you control an artifact, Toolcraft Exemplar gets +2/+1 until end of turn. If you control at least 3 artifacts, it also gains first strike until end of turn.| Wispweaver Angel|Kaladesh|35|U|{4}{W}{W}|Creature - Angel|4|4|Flying$When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control.| Aether Tradewinds|Kaladesh|38|C|{2}{U}|Instant|||Return target permanent you control and target permanent you don't control to their owners' hands.| +Aethersquall Ancient|Kaladesh|39|R|{5}{U}{U}|Creature - Leviathan|6|6|Flying$At the beginning of your upkeep, you get {E}{E}{E} (three energy counters).$Pay {E}{E}{E}{E}{E}{E}{E}{E}: Return all other creatures to their owners' hands. Activate this ability only any time you could cast a sorcery.| Ceremonious Rejection|Kaladesh|40|U|{U}|Instant|||Counter target colorless spell.| Curio Vendor|Kaladesh|42|C|{1}{U}|Creature - Vedalken|2|1|| +Disappearing Trick|Kaladesh|43|U|{1}{U}{U}|Instant|||As an additional cost to cast Disappearing Trick, return a permanent you control to its owner's hand.$Counter target spell.| +Experimental Aviator|Kaladesh|46|U|{3}{U}{U}|Creature - Human Artificer|0|3|Flying$When Experimental Aviator enters the battlefield, create two 1/1 colorless Thopter artifact creature tokens with flying.| Glint-Nest Crane|Kaladesh|50|U|{1}{U}|Creature - Bird|1|3|Flying$When Glint-Nest Crane enters the battlefield, look at the top four cards of your library. You may reveal an artifact card from among them and put it into your hand. Put the rest on the bottom of your library in any order.| +Long-Finned Skywhale|Kaladesh|54|U|{2}{U}{U}|Creature - Whale|4|3|Flying$Long-Finned Skywhale can block only creatures with flying.| Metallurgic Summonings|Kaladesh|56|M|{3}{U}{U}|Enchantment|||Whenever you cast an instant or sorcery spell, create an X/X colorless Construct artifact creature token, where X is that spell's converted mana cost.${3}{U}{U}, Exile Metallurgic Summons: Return all instant and sorcery cards from your graveyard to your hand. Activate this ability only if you control six or more artifacts.| -Padeem, Consul of Innovation|Kaladesh|R|{3}{U}|Legendary Creature - Vedalken Artificer|1|4|Artifacts you control have hexproof.$At the beginning of your upkeep, if you control the artifact with the highest converted mana cost or tied for the highest converted mana cost, draw a card.| +Nimble Innovator|Kaladesh|58|C|{3}{U}|Creature - Vedalken Artificer|2|2|When Nimble Innovator enters the battlefield, draw a card.| +Padeem, Consul of Innovation|Kaladesh|59|R|{3}{U}|Legendary Creature - Vedalken Artificer|1|4|Artifacts you control have hexproof.$At the beginning of your upkeep, if you control the artifact with the highest converted mana cost or tied for the highest converted mana cost, draw a card.| Paradoxical Outcome|Kaladesh|60|R|{3}{U}|Instant|||Return any number of target nonland, nontoken permanents you control to their owners' hands. Draw a card for each card return to your hand this way.| Saheeli's Artistry|Kaladesh|62|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except that it's an artifact in addition to its other types.| Shrewd Negotiation|Kaladesh|64|U|{4}{U}|Sorcery|||Exchange control of target artifact you control and target artifact or creature you don't control.| +Tezzeret's Ambition|Kaladesh|65|C|{3}{U}{U}|Sorcery|||Draw three cards. If you control no artifacts, discard a card.| Thriving Turtle|Kaladesh|66|C|{U}|Creature - Turtle|0|3|When Thriving Turtle enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Turtle attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Torrential Gearhulk|Kaladesh|67|M|{4}{U}{U}|Artifact Creature - Construct|5|6|Flash$When Torrential Gearhulk enters the battlefield, you may cast target instant card from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead.| +Weldfast Wingsmith|Kaladesh|69|C|{3}{U}|Creature - Human Artificer|3|3|Whenever an artifact enters the battlefield under your control, Weldfast Wingsmith gains flying until end of turn.| Aetherborn Marauder|Kaladesh|71|U|{3}{B}|Creature - Aetherborn Rogue|2|2|Flying, lifelink$When Aetherborn Marauder enters the battlefield, move any number of +1/+1 counters from other permanents you control onto Aetherborn Marauder.| -Demon of Dark Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Dark Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (an energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control.| +Ambitious Aetherborn|Kaladesh|72|C|{4}{B}|Creature - Aetherborn Artificer|4|3|Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Demon of Dark Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Dark Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (an energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefield under your control tapped.| Die Young|Kaladesh|76|C|{1}{B}|Sorcery|||Choose target creature. You get {E}{E} (two energy counters), then you may pay any amount of {E}. The creature gets -1/-1 until end of turn for each {E} paid this way.| Eliminate the Competition|Kaladesh|78|R|{4}{B}|Sorcery|||As an additional cost to cast Eliminate the Competition, sacrifice X creatures.$Destroy X target creatures.| Essence Extraction|Kaladesh|80|U|{1}{B}{B}|Instant|||Essence Extraction deals 3 damage to target creature and you gain 3 life.| Fortuitous Find|Kaladesh|81|C|{2}{B}|Sorcery|||Choose one or both — Return target artifact card from your graveyard to your hand.; or Return target creature card from your graveyard to your hand.| Gonti, Lord of Luxury|Kaladesh|84|R|{2}{B}{B}|Legendary Creature - Aetherborn Rogue|2|3|Deathtouch$When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.| Lawless Broker|Kaladesh|86|C|{2}{B}|Creature - Aetherborn Rogue|3|2|When Lawless Broker dies, put a +1/+1 counter on target creature you control.| -Live Fast|Kaladesh|87|C|{2}{B}|Sorcery|||You draw two cards, lose 2 life, and gain {E}{E} (two energy counters).| +Live Fast|Kaladesh|87|C|{2}{B}|Sorcery|||You draw two cards, lose 2 life, and get {E}{E} (two energy counters).| Lost Legacy|Kaladesh|88|R|{1}{B}{B}|Sorcery|||Name a nonartifact, nonland card. Search target player's graveyard, hand, and library for any number of cards with that name and exile them. That player shuffles his or her library, then draws a card for each card exiled from hand this way.| Maulfist Squad|Kaladesh|91|C|{3}{B}|Creature - Human Artificer|3|1|Menace$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| -Midnight Oil|Kaladesh|92|{R}|{2}{B}{B}|Enchantment|||Midnight Oil enters the battlefield with seven time counters on it.$At the beginning of your draw step, draw an additional card, then remove two time counters from Midnight Oil.$Your maximum hand size is equal to the number of time counters on Midnight Oil.$Whenever you discard a card, you lose 1 life.| +Midnight Oil|Kaladesh|92|R|{2}{B}{B}|Enchantment|||Midnight Oil enters the battlefield with seven time counters on it.$At the beginning of your draw step, draw an additional card, then remove two time counters from Midnight Oil.$Your maximum hand size is equal to the number of time counters on Midnight Oil.$Whenever you discard a card, you lose 1 life.| Morbid Curiosity|Kaladesh|94|U|{1}{B}{B}|Sorcery|||As an additional cost to cast Morbid Curiosity, sacrifice an artifact or creature.$Draw cards equal to the converted mana cost of the sacrificed permanent.| Noxious Gearhulk|Kaladesh|96|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When Noxious Gearhulk enters the battlefield, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.| Ovalchase Daredevil|Kaladesh|97|U|{3}{B}|Creature - Human Pilot|4|2|Whenever an artifact enters the battlefield under your control, you may return Ovalchase Daredevil from your graveyard to your hand.| Prakhata Club Security|Kaladesh|98|C|{3}{B}|Creature - Aetherborn Warrior|3|4|| Thriving Rats|Kaladesh|102|C|{1}{B}|Creature - Rat|1|2|When Thriving Rats enters the battlefield, you get {E}{E} (two energy counters(.$Whenever Thriving Rats attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Underhanded Designs|Kaladesh|104|U|{1}{B}|Enchantment|||Whenever an artifact enters the battlefield under your control, you may pay {1}. If you do, each opponent loses 1 life and you gain 1 life.${1}{B}, Sacrifice Underhanded Designs: Destroy target creature. Activate this ability only if you control two or more artifacts.| +Weaponcraft Enthusiast|Kaladesh|105|U|{2}{B}|Creature - Aetherborn Artificer|0|1|Fabricate 2 (When this creature enters the battlefield, put two +1/+1 counters on it or create two 1/1 colorless Servo artifact creature tokens.)| +Brazen Scourge|Kaladesh|107|U|{1}{R}{R}|Creature - Gremlin|3|3|Haste| +Cathartic Reunion|Kaladesh|109|C|{1}{R}|Sorcery|||As an additional cost to cast Cathartic Reunion, discard two cards.$Draw three cards.| Chandra, Torch of Defiance|Kaladesh|110|M|{2}{R}{R}|Planeswalker - Chandra|||+1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent.$+1: Add {R}{R} to your mana pool.$-3: Chandra, Torch of Defiance deals 4 damage to target creature.$-7: You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player."| +Chandra's Pyrohelix|Kaladesh|111|C|{1}{R}|Instant|||Chandra's Pyrohelix deals 2 damage divided as you choose among one or two target creatures and/or players.| Combustible Gearhulk|Kaladesh|112|M|{4}{R}{R}|Artifact Creature - Construct|6|6|First strike$When Combustible Gearhulk enters the battlefield, target opponent may have you draw three cards. If the player doesn't, put the top three cards of your library into your graveyard, then Combustible Gearhulk deals damage to that player equal to the total converted mana cost of those cards.| +Demolish|Kaladesh|113|C|{3}{R}|Sorcery|||Destroy target artifact or land.| Furious Reprisal|Kaladesh|115|U|{3}{R}|Sorcery|||Furious Reprisal deals 2 damage to each of two target creatures and/or players.| Harnessed Lightning|Kaladesh|117|U|{1}{R}|Instant|||Choose target creature. You get {E}{E}{E} (three energy counters), then you may pay any amount of {E}. Harnessed Lightning deals that much damage to that creature.| Incendiary Sabotage|Kaladesh|119|U|{2}{R}{R}|Instant|||As an additional cost to cast Incendiary Sabotage, sacrifice an artifact.$Incendiary Sabotage deals 3 damage to each creature.| @@ -29709,9 +29727,11 @@ Inventor's Apprentice|Kaladesh|120|U|{R}|Creature - Human Artificer|1|2|Inventor Lathnu Hellion|Kaladesh|121|R|{2}{R}|Creature - Hellion|4|4|Haste$When Lathnu Hellion enters the battlefield, you get {E}{E} (two energy counters).$At the beginning of your end step, sacrifice Lathnu Hellion unless you pay {E}{E}.| Madcap Experiment|Kaladesh|122|R|{3}{R}|Sorcery|||Reveal cards from the top of your library until you reveal an artifact card. Put that card onto the battlefield and the rest on the bottom of your library in a random order. Madcap Experiment deals damage to you equal to the number of cards revealed this way.| Pia Nalaar|Kaladesh|124|R|{2}{R}|Legendary Creature - Human Artificer|2|2|When Pia Nalaar enters the battlefield, create a 1/1 colorless Thopter artifact creature token with flying.${1}{R}: Target artifact creature gets +1/+0 until end of turn.${1}, Sacrifice an artifact: Target creature can't block this turn.| +Reckless Fireweaver|Kaladesh|126|C|{1}{R}|Creature - Human Artificer|1|3|Whenever an artifact enters the battlefield under your control, Reckless Fireweaver deals 1 damage to each opponent.| Ruinous Gremlin|Kaladesh|128|C|{R}|Creature - Gremlin|1|1|{2}{R}, Sacrifice Ruinous Gremlin: Destroy target artifact.| Salivating Gremlins|Kaladesh|129|C|{2}{R}|Creature - Gremlin|2|3|Whenever an artifact enters the battlefield under your control, Salivating Gremlins gets +2/+0 and gains trample until end of turn.| Skyship Stalker|Kaladesh|130|R|{2}{R}{R}|Creature - Dragon|3|3|Flying${R}: Skyship Stalker gains +1/+0 until end of turn.${R}: Skyship Stalker gains first strike until end of turn.${R}: Skyship Stalker gains haste until end of turn.| +Spark of Creativity|Kaladesh|131|U|{R}|Sorcery|||Choose target creature. Exile the top card of your library. You may have Spark of Creativity deal damage to that creature equal to the converted mana cost of the exiled card. If you don't, you may play that card until end of turn.| Speedway Fanatic|Kaladesh|132|U|{1}{R}|Creature - Human Pilot|2|1|Haste$Whenever Speedway Fanatic crews a Vehicle, that Vehicle gains haste until end of turn.| Start Your Engines|Kaladesh|135|U|{3}{R}|Sorcery|||Vehicles you control becomes artifact creatures until end of turn. Creatures you control get +2/+0 until end of turn.| Territorial Devourer|Kaladesh|136|R|{3}{R}|Creature - Gremlin|2|2|Trample $Whenever you gain one or more {E} (energy counters), Territorial Devourer gets +2/+2 until end of turn.| @@ -29721,14 +29741,17 @@ Welding Sparks|Kaladesh|140|C|{2}{R}|Instant|||Welding Sparks deals X damage to Arborback Stomper|Kaladesh|142|U|{3}{G}{G}|Creature - Beast|5|4|Trample$When Arborback Stomper enters the battlefield, you gain 5 life.| Architect of the Untamed|Kaladesh|143|R|{2}{G}|Creature - Elf Artificer Druid|2|3|Whenever a land enters the battlefiend under your control, you get {E} (an energy counter).$Pay {E}{E}{E}{E}{E}{E}{E}{E}: Create a 6/6 colorless Beast artifact creature token.| Armorcraft Judge|Kaladesh|144|U|{3}{G}|Creature - Elf Artificer|3|3|When Armorcraft Judge enters the battlefield, draw a card for each creature you control with a +1/+1 counter on it.| +Attune with Aether|Kaladesh|145|C|{G}|Sorcery|||Search you library for a basic land card, reveal it, put it into your hand, then shuffle your library. You get {E}{E} (two energy counters).| Blossoming Defense|Kaladesh|146|U|{G}|Instant|||Target creature you control gets +2/+2 and gains hexproof until end of turn.| Bristling Hydra|Kaladesh|147|R|{2}{G}{G}|Creature - Hydra|4|3|When Bristling Hydra enters the battlefield, you get {E}{E}{E} (three energy counters).$Pay {E}{E}{E}: Put a +1/+1 count on Bristling Hydra. It gains hexproof until end of turn.| Cultivator of Blades|Kaladesh|151|R|{3}{G}{G}|Creature - Elf Artificer|1|1|Fabricate 2$Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power.| Dubious Challenge|Kaladesh|152|R|{3}{G}|Sorcery|||Look at the top ten cards of your library, exile up to two creature cards from among them, then shuffle your library. Target opponent may choose one of the exiled cards and put it onto the battlefield under his or her control. Put the rest onto the battlefield under your control.| Ghirapur Guide|Kaladesh|156|U|{2}{G}|Creature - Elf Scout|3|2|{2}{G}: Target creature you control can't be blocked by creatures with power 2 or less this turn.| +Highspire Artisan|Kaladesh|157|C|{2}{G}|Creature - Elf Artificer|0|3|Reach (This creature can block creatures with flying.)$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| Larger Than Life|Kaladesh|160|C|{1}{G}|Sorcery|||Target creature gets +4/+4 and gains trample until end of turn.| Longtusk Cub|Kaladesh|161|U|{1}{G}|Creature - Cat|2|2|Whenever Longtusk Cub deals combat damage to a player, you get {E}{E} (two energy counters).$Pay {E}{E}: Put a +1/+1 counter on Longtusk Cub.| Nissa, Vital Force|Kaladesh|163|M|{3}{G}{G}|Planeswalker - Nissa|||+1: Untap target land you control. Until your next turn, it becomes a 5/5 Elemental creature with haste. It's still a land.$-3: Return target permanent card from your graveyard to your hand.$-6: You get an emblem with "Whenever a land enters the battlefield under your control, you may draw a card."| +Oviya Pashiri, Sage Lifecrafter|Kaladesh|165|R|{G}|Legendary Creature - Human Artificer|1|2|{2}{G}, {T}: Create a 1/1 colorless Servo artifact creature token.${4}{G}, {T}: Create an X/X colorless Construct artifact creature token, where X is the number of creature you control.| Thriving Rhino|Kaladesh|171|C|{2}{G}|Creature - Rhino|2|3|When Thriving Rhino enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Rhino attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Verdurous Gearhulk|Kaladesh|172|M|{3}{G}{G}|Artifact Creature - Construct|4|4|Trample$When Verdurous Gearhulk enters the battlefield, distribute four +1/+1 counters among any number of target creatures you control.| Wildest Dreams|Kaladesh|174|R|{X}{X}{G}|Sorcery|||Return X target cards from your graveyard to your hand.$Exile Wildest Dreams.| @@ -29738,6 +29761,7 @@ Depala, Pilot Exemplar|Kaladesh|178|R|{1}{R}{W}|Legendary Creature - Dwarf Pilot Dovin Baan|Kaladesh|179|M|{2}{W}{U}|Planeswalker - Dovin|||+1: Until your next turn, up to one target creature gets -3/-0 and its activated abilities can't be activated.$-1: You gain 2 life and draw a card.$-7: You get an emblem with "Your opponents can't untap more than two permanents during their untap steps."| Kambal, Consul of Allocation|Kaladesh|183|R|{1}{W}{B}|Legendary Creature - Human Advisor|2|3|Whenever an opponent casts a noncreature spell, that player loses 2 life and you gain 2 life.| Rashmi, Eternities Crafter|Kaladesh|184|M|{2}{G}{U}|Legendary Creature - Elf Druid|2|3|Whenever you cast your first spell each turn, reveal the top card of your library. If it's a nonland card with converted mana cost less than that spell's, you may cast it without paying its mana cost. If you don't cast the revealed card, put it into your hand. | +Restoration Gearsmith|Kaladesh|185|U|{2}{W}{B}|Creature - Human Artificer|3|3|When Restoration Gearsmith enters the battlefield, return target artifact or creature card from your graveyard to your hand.| Saheeli Rai|Kaladesh|186|M|{1}{U}{R}|Planeswalker - Saheeli|3|+1: Scry 1. Saheeli Rai deals 1 damage to each opponent.$-2: Create a token that's a copy of target artifact or creature you control, except it's an artifact in addition to its other types. That token gains haste. Exile it at the beginning of the next end step.$-7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.| Unlicensed Disintegration|Kaladesh|187|U|{1}{B}{R}|Instant|||Destroy target creature. If you control an artifact, Unlicensed Disintegration deals 3 damage to that creature's controller.| Voltaic Brawler|Kaladesh|189|U|{R}{G}|Creature - Human Warrior|3|2|When Voltaic Brawler enters the battlefield, you get {E}{E} (two energy counters).$Whenever Voltaic Brawler attacks, you may pay {E}. If you do, it gets +1/+1 and gains trample until end of turn.| @@ -29762,12 +29786,16 @@ Glassblower's Puzzleknot|Kaladesh|217|C|{2}|Artifact|||When Glassblower's Puzzle Inventor's Goggles|Kaladesh|218|C|{1}|Artifact - Equipment|||Equipped creature gets +1/+2.$Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it.$Equip {2} ({2}: Attach to target creature you control. Equip only as a sorcery)| Key to the City|Kaladesh|220|R|{2}|Artifact|||{T}, Discard a card: Up to one target creature can't be blocked this turn.$Whenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card.| Metalspinner's Puzzleknot|Kaladesh|221|C|{2}|Artifact|||When Metalspinner's Puzzleknot enters the battlefield, you draw a card and you lose 1 life.${2}{B}, Sacrifice Metalspinner's Puzzleknot: You draw a card and you lose 1 life.| +Metalwork Colossus|Kaladesh|222|R|{11}|Artifact Creature - Construct|10|10|Metalwork Colossus costs {X} less to cast, where X is the total converted mana cost of noncreature artifacts you control.$Sacrifice two artifacts: Return Metalwork Colossus from your graveyard to your hand.| Ovalchase Dragster|Kaladesh|225|U|{4}|Artifact - Vehicle|6|1|Trample, haste$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| Panharmonicon|Kaladesh|226|R|{4}|Artifact|||If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.| +Perpetual Timepiece|Kaladesh|227|U|{2}|Artifact|||{T}: Put the top two cards of your library into your graveyard.${2}, Exile Perpetual Timepiece: Shuffle any number of target cards from your graveyard into your libary.| +Prophetic Prism|Kaladesh|229|C|{2}|Artifact|||When Prophetic Prism enters the battlefield, draw a card.${1}, {T}: Add one mana of any color to your mana pool.| Scrapheap Scrounger|Kaladesh|231|R|{2}|Artifact Creature - Construct|3|2|Scrapheap Scrounger can't block.${1}{B}, Exile another creature card from your graveyard: Return Scrapheap Scrounger from your graveyard to the battlefield.| Sky Skiff|Kaladesh|233|C|{2}|Artifact - Vehicle|2|3|Flying$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| Skysovereign, Consul Flagship|Kaladesh|234|M|{5}|Legendary Artifact - Vehicle|6|5|Flying$Whenever Skysovereign, Consul Flagship enters the battlefield or attacks, it deals 3 damage to target creature or planeswalker an opponent controls.$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.)| Smuggler's Copter|Kaladesh|235|R|{2}|Artifact - Vehicle|3|3|Flying$Whenever Smuggler's Copter attacks or blocks, you may draw a card. If you do, discard a card.$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| +Torch Gauntlet|Kaladesh|237|C|{2}|Artifact - Equipment|||Equipped creature gets +2/+0.$Equip {2} ({2}: Attech to target creature you control. Equip only as a sorcery.)| Whirlermaker|Kaladesh|239|U|{3}|Artifact|||{4}, {T}: Create a 1/1 colorless Thopter artifact creature token with flying.| Woodweaver's Puzzleknot|Kaladesh|240|C|{2}|Artifact|||When Woodweaver's Puzzleknot enters the battlefield, you gain 3 life and get {E}{E}{E} (three energy counters).${2}{G}, Sacrifice Woodweaver's Puzzleknot: You gain 3 life and get {E}{E}{E}.| Aether Hub|Kaladesh|242|U||Land|||When Aether Hub enters the battlefield, you get {E} (an energy counter).${T}: Add {C} to your mana pool.${T}, Pay {E}: Add one mana of any color to your mana pool.| @@ -29793,7 +29821,15 @@ Forest|Kaladesh|261|L||Basic Land - Forest|||G| Forest|Kaladesh|262|L||Basic Land - Forest|||G| Forest|Kaladesh|263|L||Basic Land - Forest|||G| Chandra, Pyrogenius|Kaladesh|265|M|{4}{R}{R}|Planeswalker - Chandra|||+2: Chandra, Pyrogenius deals 2 damage to each opponent.$-3: Chandra, Pyrogenius deals 4 damage to target creature.$-10: Chandra, Pyrogenius deals 6 damage to target player and each creature he or she controls.| +Flame Lash|Kaladesh|266|C|{3}{R}|Instant|||Flame Lash deals 4 damage to target creature or player.| +Liberating Combustion|Kaladesh|267|R|{4}{R}|Sorcery|||Liberating Combustion deals 6 damage to target creature. You may search you library and/or graveyard for a card named Chandra, Pyrogenius, reveal it, and put it into your hand. If you search your library this way, shuffle it.| +Renegade Firebrand|Kaladesh|268|U|{2}{R}|Creature - Human Warrior|3|2|As long as you control a Chandra planeswalker, Renegade Firebrand gets +1/+0 and has first strike.| +Stone Quarry|Kaladesh|269|C||Land|||Stone Quarry enters the battlefield tapped.${T}: Add {R} or {W} to your mana pool.| Nissa, Nature's Artisan|Kaladesh|270|M|{4}{G}{G}|Planeswalker - Nissa|||+3: You gain 3 life.$-4: Reveal the top two cards of your library. Put all land cards from among them onto the battlefield and the rest into your hand.$-12: Creatures you control get +5/+5 and gain trample until end of turn.| +Guardian of the Great Conduit|Kaladesh|271|U|{3}{G}|Creature - Elemental|2|4|Reach (This creature can block creature with flying.)$As long as you control a Nissa planeswalker, Guardian of the Great Conduit gets +2/+0 and has vigilance. (Attacking doesn't cause it to tap.)| +Terrain Elemental|Kaladesh|272|C|{1}{G}|Creature - Elemental|3|2|| +Verdant Crescendo|Kaladesh|273|R|{3}{G}|Sorcery|||Search your library for a basic land card and put it onto the battlefield tapped. Search your library and graveyard for a card named Nissa, Nature's Artisan, reveal it, and put it into your hand. Then shuffle your library.| +Woodland Stream|Kaladesh|274|C||Land|||Woodland Stream enters the battlefield tapped.${T}: Add {G} or {U} to your mana pool.| Cataclysmic Gearhulk|Masterpiece Series|1|M|{3}{W}{W}|Artifact Creature - Construct|4|5|Vigilance$When Cataclysmic Gearhulk enters the battlefield, each player chooses an artifact, a creature, an enchantment, and a planeswalker from among the nonland permanents he or she controls, the sacrifices the rest.| Combustible Gearhulk|Masterpiece Series|2|M|{4}{R}{R}|Artifact Creature - Construct|6|6|First strike$When Combustible Gearhulk enters the battlefield, target opponent may have you draw three cards. If the player doesn't, put the top three cards of your library into your graveyard, then Combustible Gearhulk deals damage to that player equal to the total converted mana cost of those cards.| Noxious Gearhulk|Masterpiece Series|3|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When Noxious Gearhulk enters the battlefield, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.|