Merge branch 'master' into implement-double-vision

This commit is contained in:
Evan Kranzler 2020-06-05 21:21:32 -04:00 committed by GitHub
commit 8b50195a08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
97 changed files with 474 additions and 164 deletions

View file

@ -1259,10 +1259,10 @@ public class GameController implements GameCallback {
.collect(Collectors.joining(", ")));
StringBuilder sb = new StringBuilder();
sb.append("<font color='red'>FIX command called by " + user.getName() + "</font>");
sb.append("<font color='red'>FIX command called by ").append(user.getName()).append("</font>");
sb.append("<font size='-2'>"); // font resize start for all next logs
sb.append("<br>Game ID: " + game.getId());
sb.append("<br>Game ID: ").append(game.getId());
sb.append("<br>Phase: ").append(game.getTurn().getPhaseType().toString()).append(" Step: ").append(game.getTurn().getStepType().toString());
// pings info
sb.append("<br>");
sb.append(getPingsInfo());
@ -1272,7 +1272,7 @@ public class GameController implements GameCallback {
// fix active
Player playerActive = game.getPlayer(state.getActivePlayerId());
sb.append("<br>Fixing active player: " + getName(playerActive));
sb.append("<br>Fixing active player: ").append(getName(playerActive));
if (playerActive != null && !playerActive.canRespond()) {
fixActions.add("active player fix");
@ -1280,16 +1280,16 @@ public class GameController implements GameCallback {
sb.append("<br>Try to concede...");
playerActive.concede(game);
playerActive.leave(); // abort any wait response actions
sb.append(" (" + asWarning("OK") + ", concede done)");
sb.append(" (").append(asWarning("OK")).append(", concede done)");
sb.append("<br>Try to skip step...");
Phase currentPhase = game.getPhase();
if (currentPhase != null) {
currentPhase.getStep().skipStep(game, state.getActivePlayerId());
fixedAlready = true;
sb.append(" (" + asWarning("OK") + ", skip step done)");
sb.append(" (").append(asWarning("OK")).append(", skip step done)");
} else {
sb.append(" (" + asBad("FAIL") + ", step is null)");
sb.append(" (").append(asBad("FAIL")).append(", step is null)");
}
} else {
sb.append(playerActive != null ? " (" + asGood("OK") + ", can respond)" : " (" + asGood("OK") + ", no player)");
@ -1297,7 +1297,7 @@ public class GameController implements GameCallback {
// fix lost choosing dialog
Player choosingPlayer = game.getPlayer(state.getChoosingPlayerId());
sb.append("<br>Fixing choosing player: " + getName(choosingPlayer));
sb.append("<br>Fixing choosing player: ").append(getName(choosingPlayer));
if (choosingPlayer != null && !choosingPlayer.canRespond()) {
fixActions.add("choosing player fix");
@ -1305,7 +1305,7 @@ public class GameController implements GameCallback {
sb.append("<br>Try to concede...");
choosingPlayer.concede(game);
choosingPlayer.leave(); // abort any wait response actions
sb.append(" (" + asWarning("OK") + ", concede done)");
sb.append(" (").append(asWarning("OK")).append(", concede done)");
sb.append("<br>Try to skip step...");
if (fixedAlready) {
@ -1315,9 +1315,9 @@ public class GameController implements GameCallback {
if (currentPhase != null) {
currentPhase.getStep().skipStep(game, state.getActivePlayerId());
fixedAlready = true;
sb.append(" (" + asWarning("OK") + ", skip step done)");
sb.append(" (").append(asWarning("OK")).append(", skip step done)");
} else {
sb.append(" (" + asBad("FAIL") + ", step is null)");
sb.append(" (").append(asBad("FAIL")).append(", step is null)");
}
}
} else {
@ -1326,7 +1326,7 @@ public class GameController implements GameCallback {
// fix lost priority
Player priorityPlayer = game.getPlayer(state.getPriorityPlayerId());
sb.append("<br>Fixing priority player: " + getName(priorityPlayer));
sb.append("<br>Fixing priority player: ").append(getName(priorityPlayer));
if (priorityPlayer != null && !priorityPlayer.canRespond()) {
fixActions.add("priority player fix");
@ -1334,19 +1334,19 @@ public class GameController implements GameCallback {
sb.append("<br>Try to concede...");
priorityPlayer.concede(game);
priorityPlayer.leave(); // abort any wait response actions
sb.append(" (" + asWarning("OK") + ", concede done)");
sb.append(" (").append(asWarning("OK")).append(", concede done)");
sb.append("<br>Try to skip step...");
if (fixedAlready) {
sb.append(" (" + asWarning("OK") + ", already skipped before)");
sb.append(" (").append(asWarning("OK")).append(", already skipped before)");
} else {
Phase currentPhase = game.getPhase();
if (currentPhase != null) {
currentPhase.getStep().skipStep(game, state.getActivePlayerId());
fixedAlready = true;
sb.append(" (" + asWarning("OK") + ", skip step done)");
sb.append(" (").append(asWarning("OK")).append(", skip step done)");
} else {
sb.append(" (" + asBad("FAIL") + ", step is null)");
sb.append(" (").append(asBad("FAIL")).append(", step is null)");
}
}
} else {
@ -1356,10 +1356,10 @@ public class GameController implements GameCallback {
// fix timeout
sb.append("<br>Fixing future timeout: ");
if (futureTimeout != null) {
sb.append("cancelled?=" + futureTimeout.isCancelled());
sb.append("...done?=" + futureTimeout.isDone());
sb.append("cancelled?=").append(futureTimeout.isCancelled());
sb.append("...done?=").append(futureTimeout.isDone());
int delay = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
sb.append("...getDelay?=" + delay);
sb.append("...getDelay?=").append(delay);
if (delay < 25) {
fixActions.add("future timeout fix");
@ -1367,12 +1367,12 @@ public class GameController implements GameCallback {
sb.append("<br>Try to pass...");
PassAbility pass = new PassAbility();
game.endTurn(pass);
sb.append(" (" + asWarning("OK") + ", pass done)");
sb.append(" (").append(asWarning("OK")).append(", pass done)");
} else {
sb.append(" (" + asGood("OK") + ", delay > 25)");
sb.append(" (").append(asGood("OK")).append(", delay > 25)");
}
} else {
sb.append(" (" + asGood("OK") + ", timeout is not using)");
sb.append(" (").append(asGood("OK")).append(", timeout is not using)");
}
// TODO: fix non started game (send game started event to user?)
@ -1382,7 +1382,7 @@ public class GameController implements GameCallback {
fixActions.add("none");
}
String appliedFixes = fixActions.stream().collect(Collectors.joining(", "));
sb.append("<br>Applied fixes: " + appliedFixes);
sb.append("<br>Applied fixes: ").append(appliedFixes);
sb.append("</font>"); // font resize end
sb.append("<br>");

View file

@ -21,7 +21,7 @@ public final class AbzanBeastmaster extends CardImpl {
public AbzanBeastmaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);

View file

@ -19,7 +19,7 @@ public final class AerieBowmasters extends CardImpl {
public AerieBowmasters(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(3);
this.toughness = new MageInt(4);

View file

@ -17,7 +17,6 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
/**
*

View file

@ -23,7 +23,7 @@ public final class AffaGuardHound extends CardImpl {
public AffaGuardHound (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -23,7 +23,7 @@ public final class AinokArtillerist extends CardImpl {
public AinokArtillerist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(4);
this.toughness = new MageInt(1);

View file

@ -33,7 +33,7 @@ public final class AinokBondKin extends CardImpl {
public AinokBondKin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(2);

View file

@ -25,7 +25,7 @@ public final class AinokGuide extends CardImpl {
public AinokGuide(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -31,7 +31,7 @@ public final class AinokSurvivalist extends CardImpl {
public AinokSurvivalist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);

View file

@ -19,7 +19,7 @@ public final class AinokTracker extends CardImpl {
public AinokTracker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(3);

View file

@ -23,7 +23,7 @@ public final class AkroanMastiff extends CardImpl {
public AkroanMastiff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -34,11 +34,13 @@ public final class ArmoredAscension extends CardImpl {
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Enchanted creature gets +1/+1 for each Plains you control and has flying.
PermanentsOnBattlefieldCount amount = new PermanentsOnBattlefieldCount(filter, 1);
SimpleStaticAbility ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(amount, amount, Duration.WhileOnBattlefield));
ability.addEffect(new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA));

View file

@ -19,7 +19,7 @@ public final class AshmouthHound extends CardImpl {
public AshmouthHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(1);

View file

@ -39,7 +39,7 @@ public final class BINGO extends CardImpl {
public BINGO(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -19,7 +19,7 @@ public final class Banehound extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
this.subtype.add(SubType.NIGHTMARE);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -25,7 +25,7 @@ public final class BlazingHellhound extends CardImpl {
public BlazingHellhound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}");
this.subtype.add(SubType.ELEMENTAL, SubType.HOUND);
this.subtype.add(SubType.ELEMENTAL, SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(3);

View file

@ -26,7 +26,7 @@ public final class BloodHound extends CardImpl {
public BloodHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -23,7 +23,7 @@ public final class BorosMastiff extends CardImpl {
public BorosMastiff (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -27,7 +27,7 @@ public final class CatharsCompanion extends CardImpl {
public CatharsCompanion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(1);

View file

@ -19,7 +19,7 @@ public final class CausticHound extends CardImpl {
public CausticHound (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{B}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(4);

View file

@ -25,7 +25,7 @@ public final class ChakramRetriever extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(4);

View file

@ -17,7 +17,7 @@ public final class ChampionOfArashin extends CardImpl {
public ChampionOfArashin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(2);

View file

@ -30,7 +30,7 @@ public final class CorpseCur extends CardImpl {
public CorpseCur (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.addAbility(InfectAbility.getInstance());

View file

@ -6,7 +6,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
@ -16,12 +15,14 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.targetadjustment.TargetAdjuster;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.abilities.condition.Condition;
import mage.constants.Zone;
/**
* @author TheElk801
@ -31,7 +32,8 @@ public final class DecoyGambit extends CardImpl {
public DecoyGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
// For each opponent, choose up to one target creature that player controls, then return that creature to its owner's hand unless its controller has you draw a card.
// For each opponent, choose up to one target creature that player controls,
// then return that creature to its owner's hand unless its controller has you draw a card.
this.getSpellAbility().addEffect(new DecoyGambitEffect());
this.getSpellAbility().setTargetAdjuster(DecoyGambitAdjuster.instance);
}
@ -70,8 +72,8 @@ class DecoyGambitEffect extends OneShotEffect {
DecoyGambitEffect() {
super(Outcome.Benefit);
staticText = "For each opponent, choose up to one target creature that player controls, " +
"then return that creature to its owner's hand unless its controller has you draw a card.";
staticText = "For each opponent, choose up to one target creature that player controls, "
+ "then return that creature to its owner's hand unless its controller has you draw a card.";
}
private DecoyGambitEffect(final DecoyGambitEffect effect) {
@ -86,6 +88,8 @@ class DecoyGambitEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
HashSet<Permanent> permanentToHand = new HashSet();
int numberOfCardsToDraw = 0;
if (controller == null) {
return false;
}
@ -98,16 +102,54 @@ class DecoyGambitEffect extends OneShotEffect {
.filter(Objects::nonNull)
.collect(Collectors.toList());
for (Permanent permanent : permanents) {
// If a creature targeted by Decoy Gambit changes controller, its no longer a legal target.
new DecoyGambitCondition(permanent).apply(game, source); // save current controller
Player player = game.getPlayer(permanent.getControllerId());
if (player == null) {
continue;
}
if (player.chooseUse(outcome, "Have " + controller.getName() + " draw a card? If you don't, " +
permanent.getName() + " will be returned to its owner's hand.", source, game)
&& controller.drawCards(1, source.getSourceId(), game) > 0) {
player.moveCards(permanent, Zone.HAND, source, game);
if (player.chooseUse(outcome, "Have " + controller.getName() + " draw a card? If you don't, "
+ permanent.getName() + " will be returned to its owner's hand.", source, game)) {
game.informPlayers(player.getName() + " chose to have " + controller.getName() + " draw a card.");
numberOfCardsToDraw += 1;
} else {
game.informPlayers(player.getName() + " chose to have their creature returned to their hand.");
permanentToHand.add(permanent);
}
}
/*
As the Decoy Gambit resolves, first the next opponent in turn order (or, if its an opponents
turn, the opponent whose turn it is) chooses whether youll draw a card or return their creature
that was targeted to its owners hand, then each other opponent in turn order does so knowing
the choices made before them. After all choices are made, you draw the appropriate number of
cards. After youve drawn, the appropriate creatures are all simultaneously returned to their owners hands.
*/
controller.drawCards(numberOfCardsToDraw, source.getSourceId(), game);
for (Permanent creature : permanentToHand) {
if (creature != null
&& new DecoyGambitCondition(creature).apply(game, source)) { // same controller required
creature.moveToZone(Zone.HAND, source.getSourceId(), game, false);
}
}
return true;
}
}
class DecoyGambitCondition implements Condition {
private UUID controllerId;
private final Permanent permanent;
DecoyGambitCondition(Permanent permanent) {
this.permanent = permanent;
}
@Override
public boolean apply(Game game, Ability source) {
if (controllerId == null) { // is the original controller set
controllerId = permanent.getControllerId(); // original controller set
}
return (permanent != null
&& Objects.equals(controllerId, permanent.getControllerId()));
}
}

View file

@ -22,7 +22,7 @@ public final class DrossRipper extends CardImpl {
public DrossRipper (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}")));

View file

@ -19,7 +19,7 @@ public final class ElvenWarhounds extends CardImpl {
public ElvenWarhounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -26,7 +26,7 @@ public final class EncampmentKeeper extends CardImpl {
public EncampmentKeeper(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -23,7 +23,7 @@ public final class FieryHellhound extends CardImpl {
public FieryHellhound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -23,7 +23,7 @@ public final class FilthyCur extends CardImpl {
public FilthyCur(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -24,7 +24,7 @@ public final class GateHound extends CardImpl {
public GateHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -31,7 +31,7 @@ public final class GhostHounds extends CardImpl {
public GhostHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -23,7 +23,7 @@ public final class GoreVassal extends CardImpl {
public GoreVassal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(1);

View file

@ -18,7 +18,7 @@ public final class GreaterMossdog extends CardImpl {
public GreaterMossdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.PLANT);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -30,7 +30,7 @@ public final class GuardDogs extends CardImpl {
public GuardDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -25,7 +25,7 @@ public final class HellfireMongrel extends CardImpl {
public HellfireMongrel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -20,7 +20,7 @@ public final class HollowDogs extends CardImpl {
public HollowDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -36,7 +36,7 @@ public final class HollowbornBarghest extends CardImpl {
public HollowbornBarghest(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}");
this.subtype.add(SubType.DEMON);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(7);
this.toughness = new MageInt(6);

View file

@ -19,7 +19,7 @@ public final class HoundOfGriselbrand extends CardImpl {
public HoundOfGriselbrand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -28,7 +28,7 @@ public final class HoundOfTheFarbogs extends CardImpl {
public HoundOfTheFarbogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(5);
this.toughness = new MageInt(3);

View file

@ -32,7 +32,7 @@ public final class Hydradoodle extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{X}{G}{G}");
this.subtype.add(SubType.HYDRA);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(0);
this.toughness = new MageInt(0);

View file

@ -22,7 +22,7 @@ public final class ImmolatingSouleater extends CardImpl {
public ImmolatingSouleater(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -19,7 +19,7 @@ public final class IsamaruHoundOfKonda extends CardImpl {
public IsamaruHoundOfKonda(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -24,7 +24,7 @@ public final class KarplusanHound extends CardImpl {
public KarplusanHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("a Chandra planeswalker");

View file

@ -26,7 +26,7 @@ public final class KunorosHoundOfAthreos extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -19,7 +19,7 @@ public final class LavaHounds extends CardImpl {
public LavaHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(4);

View file

@ -28,7 +28,7 @@ public final class Leashling extends CardImpl {
public Leashling(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{6}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -17,7 +17,7 @@ public final class LightningHounds extends CardImpl {
public LightningHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(2);

View file

@ -35,7 +35,7 @@ public final class LongshotSquad extends CardImpl {
public LongshotSquad(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(3);

View file

@ -110,7 +110,7 @@ class LurkingJackalsToken extends TokenImpl {
public LurkingJackalsToken() {
super("Hound", "3/2 Hound creature");
cardType.add(CardType.CREATURE);
subtype.add(SubType.HOUND);
subtype.add(SubType.DOG);
power = new MageInt(3);
toughness = new MageInt(2);
}

View file

@ -30,7 +30,7 @@ public final class MadDog extends CardImpl {
public MadDog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -116,7 +116,7 @@ class MangaraTheDiplomatCastTriggeredAbility extends TriggeredAbilityImpl {
return player != null
&& watcher != null
&& player.hasOpponent(event.getPlayerId(), game)
&& watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 3;
&& watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2;
}
@Override

View file

@ -2,7 +2,6 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -21,6 +20,8 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.game.permanent.token.RatToken;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author LevelX
@ -50,9 +51,11 @@ public final class MarrowGnawer extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(FearAbility.getInstance(), Duration.WhileOnBattlefield, filterFear)));
// {T}, Sacrifice a Rat: create X 1/1 black Rat creature tokens, where X is the number of Rats you control.
Ability ability;
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new RatToken(),new PermanentsOnBattlefieldCount(filter3)), new SacrificeTargetCost(new TargetControlledPermanent(filterSacrifice)));
ability.addCost(new TapSourceCost());
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new CreateTokenEffect(new RatToken(), new PermanentsOnBattlefieldCount(filter3, null))
/*.setText("create X 1/1 black Rat creature tokens, where X is the number of Rats you control")*/,
new TapSourceCost());
ability.addCost( new SacrificeTargetCost(new TargetControlledPermanent(filterSacrifice)));
this.addAbility(ability);
}

View file

@ -26,7 +26,7 @@ public final class MogissWarhound extends CardImpl {
public MogissWarhound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.ZoneChangeTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@ -13,18 +11,18 @@ import mage.constants.TurnPhase;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.DogToken;
import java.util.UUID;
/**
*
* @author North
*/
public final class MongrelPack extends CardImpl {
public MongrelPack(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(1);
@ -33,7 +31,7 @@ public final class MongrelPack extends CardImpl {
this.addAbility(new MongrelPackAbility());
}
public MongrelPack(final MongrelPack card) {
private MongrelPack(final MongrelPack card) {
super(card);
}
@ -45,11 +43,11 @@ public final class MongrelPack extends CardImpl {
class MongrelPackAbility extends ZoneChangeTriggeredAbility {
public MongrelPackAbility() {
super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CreateTokenEffect(new HoundToken(), 4), "When {this} dies during combat, ", false);
MongrelPackAbility() {
super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CreateTokenEffect(new DogToken(), 4), "When {this} dies during combat, ", false);
}
public MongrelPackAbility(MongrelPackAbility ability) {
private MongrelPackAbility(MongrelPackAbility ability) {
super(ability);
}
@ -68,24 +66,3 @@ class MongrelPackAbility extends ZoneChangeTriggeredAbility {
return false;
}
}
class HoundToken extends TokenImpl {
public HoundToken() {
super("Hound", "1/1 green Hound creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.HOUND);
color.setGreen(true);
power = new MageInt(1);
toughness = new MageInt(1);
}
public HoundToken(final HoundToken token) {
super(token);
}
public HoundToken copy() {
return new HoundToken(this);
}
}

View file

@ -26,7 +26,7 @@ public final class MonstrousHound extends CardImpl {
public MonstrousHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(4);

View file

@ -30,7 +30,7 @@ public final class MoonEatingDog extends CardImpl {
public MoonEatingDog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -24,7 +24,7 @@ public final class MortisDogs extends CardImpl {
public MortisDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -24,7 +24,7 @@ public final class Mossdog extends CardImpl {
public Mossdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
this.subtype.add(SubType.PLANT);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -25,7 +25,7 @@ public final class MowuLoyalCompanion extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -0,0 +1,41 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.common.DrawSecondCardTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class MysticSkyfish extends CardImpl {
public MysticSkyfish(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.FISH);
this.power = new MageInt(3);
this.toughness = new MageInt(1);
// Whenever you draw your second card each turn, Mystic Skyfish gains flying until end of turn.
this.addAbility(new DrawSecondCardTriggeredAbility(
new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), false)
);
}
private MysticSkyfish(final MysticSkyfish card) {
super(card);
}
@Override
public MysticSkyfish copy() {
return new MysticSkyfish(this);
}
}

View file

@ -28,7 +28,7 @@ public final class PackMastiff extends CardImpl {
public PackMastiff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -29,7 +29,7 @@ public final class PakoArcaneRetriever extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -22,7 +22,7 @@ public final class PatrolHound extends CardImpl {
public PatrolHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -22,7 +22,7 @@ public final class PhantomWhelp extends CardImpl {
public PhantomWhelp(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
this.subtype.add(SubType.ILLUSION);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -26,7 +26,7 @@ public final class PlagueDogs extends CardImpl {
public PlagueDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -22,7 +22,7 @@ public final class PyreHound extends CardImpl {
public PyreHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(3);

View file

@ -19,7 +19,7 @@ public final class RakdosRagemutt extends CardImpl {
public RakdosRagemutt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -25,7 +25,7 @@ public final class ResoluteWatchdog extends CardImpl {
public ResoluteWatchdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(3);

View file

@ -23,7 +23,7 @@ public final class SaltRoadAmbushers extends CardImpl {
public SaltRoadAmbushers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -18,7 +18,7 @@ public final class SandsteppeScavenger extends CardImpl {
public SandsteppeScavenger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -26,7 +26,7 @@ public final class ScrapyardMongrel extends CardImpl {
public ScrapyardMongrel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.color.setRed(true);
this.power = new MageInt(3);

View file

@ -0,0 +1,51 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.keyword.ProwessAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterInstantOrSorceryCard;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ShipwreckDowser extends CardImpl {
private static final FilterCard filter
= new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard");
public ShipwreckDowser(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
this.subtype.add(SubType.MERFOLK);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Prowess
this.addAbility(new ProwessAbility());
// When Shipwreck Dowser enters the battlefield, return target instant or sorcery card from your graveyard to your hand.
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
private ShipwreckDowser(final ShipwreckDowser card) {
super(card);
}
@Override
public ShipwreckDowser copy() {
return new ShipwreckDowser(this);
}
}

View file

@ -35,7 +35,7 @@ public final class SnowHound extends CardImpl {
public SnowHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -0,0 +1,41 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StormCaller extends CardImpl {
public StormCaller(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.OGRE);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// When Storm Caller enters the battlefield, it deals 2 damage to each opponent.
this.addAbility(new EntersBattlefieldTriggeredAbility(
new DamagePlayersEffect(2, TargetController.OPPONENT, "it")
));
}
private StormCaller(final StormCaller card) {
super(card);
}
@Override
public StormCaller copy() {
return new StormCaller(this);
}
}

View file

@ -0,0 +1,45 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TeferisProtege extends CardImpl {
public TeferisProtege(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// {1}{U}, {T}: Draw a card, then discard a card.
Ability ability = new SimpleActivatedAbility(
new DrawDiscardControllerEffect(1, 1), new ManaCostsImpl("{1}{U}")
);
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
private TeferisProtege(final TeferisProtege card) {
super(card);
}
@Override
public TeferisProtege copy() {
return new TeferisProtege(this);
}
}

View file

@ -29,7 +29,10 @@ public final class ThassasOracle extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// When Thassa's Oracle enters the battlefield, look at the top X cards of your library, where X is your devotion to blue. Put one of them on top of your library and the rest on the bottom of your library in a random order. If X is greater than or equal to the number of cards in your library, you win the game.
// When Thassa's Oracle enters the battlefield, look at the top X cards of your library, where X is your devotion to blue.
// Put up to one of them on top of your library and the rest on the bottom of your library in a random order.
// If X is greater than or equal to the number of cards in your library, you win the game.
// (Each Blue in the mana costs of permanents you control counts toward your devotion to blue.)
this.addAbility(new EntersBattlefieldTriggeredAbility(new ThassasOracleEffect())
.addHint(DevotionCount.U.getHint()));
}

View file

@ -26,7 +26,7 @@ public final class ThrabenFoulbloods extends CardImpl {
public ThrabenFoulbloods(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(2);

View file

@ -16,7 +16,7 @@ public final class ThrabenPurebloods extends CardImpl {
public ThrabenPurebloods(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(5);

View file

@ -23,7 +23,7 @@ public final class ThrashingMossdog extends CardImpl {
public ThrashingMossdog (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.PLANT);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -17,7 +17,7 @@ public final class TwoHeadedCerberus extends CardImpl {
public TwoHeadedCerberus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(2);

View file

@ -25,7 +25,7 @@ public final class UnderworldCerberus extends CardImpl {
public UnderworldCerberus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(6);
this.toughness = new MageInt(6);

View file

@ -20,7 +20,7 @@ public final class UnderworldRageHound extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(1);

View file

@ -23,7 +23,7 @@ public final class VampireHounds extends CardImpl {
public VampireHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.VAMPIRE);
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -17,7 +17,7 @@ public final class WarclampMastiff extends CardImpl {
public WarclampMastiff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);

View file

@ -28,7 +28,7 @@ public final class Watchdog extends CardImpl {
public Watchdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(2);

View file

@ -30,7 +30,7 @@ public final class WildDogs extends CardImpl {
public WildDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(1);

View file

@ -24,7 +24,7 @@ public final class WildMongrel extends CardImpl {
public WildMongrel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -30,7 +30,7 @@ public final class WildfireCerberus extends CardImpl {
public WildfireCerberus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(3);

View file

@ -0,0 +1,37 @@
package mage.cards.w;
import mage.MageInt;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class WildwoodPatrol extends CardImpl {
public WildwoodPatrol(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.subtype.add(SubType.CENTAUR);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(4);
this.toughness = new MageInt(2);
// Trample
this.addAbility(TrampleAbility.getInstance());
}
private WildwoodPatrol(final WildwoodPatrol card) {
super(card);
}
@Override
public WildwoodPatrol copy() {
return new WildwoodPatrol(this);
}
}

View file

@ -17,7 +17,7 @@ public final class ZodiacDog extends CardImpl {
public ZodiacDog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
this.subtype.add(SubType.HOUND);
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

View file

@ -24,7 +24,7 @@ public final class CoreSet2021 extends ExpansionSet {
private CoreSet2021() {
super("Core Set 2021", "M21", ExpansionSet.buildDate(2020, 7, 3), SetType.CORE);
this.hasBoosters = true;
this.hasBasicLands = false; // change when basics are available
this.hasBasicLands = true;
this.numBoosterSpecial = 0;
this.numBoosterLands = 1;
this.numBoosterCommon = 10;
@ -34,6 +34,23 @@ public final class CoreSet2021 extends ExpansionSet {
this.maxCardNumberInBooster = 274;
cards.add(new SetCardInfo("Double Vision", 142, Rarity.RARE, mage.cards.d.DoubleVision.class));
cards.add(new SetCardInfo("Azusa, Lost but Seeking", 173, Rarity.RARE, mage.cards.a.AzusaLostButSeeking.class));
cards.add(new SetCardInfo("Baneslayer Angel", 4, Rarity.MYTHIC, mage.cards.b.BaneslayerAngel.class));
cards.add(new SetCardInfo("Containment Priest", 314, Rarity.RARE, mage.cards.c.ContainmentPriest.class));
cards.add(new SetCardInfo("Fierce Empath", 181, Rarity.UNCOMMON, mage.cards.f.FierceEmpath.class));
cards.add(new SetCardInfo("Grim Tutor", 103, Rarity.MYTHIC, mage.cards.g.GrimTutor.class));
cards.add(new SetCardInfo("Island", 310, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Jeskai Elder", 53, Rarity.UNCOMMON, mage.cards.j.JeskaiElder.class));
cards.add(new SetCardInfo("Mangara, the Diplomat", 27, Rarity.MYTHIC, mage.cards.m.MangaraTheDiplomat.class));
cards.add(new SetCardInfo("Mystic Skyfish", 326, Rarity.COMMON, mage.cards.m.MysticSkyfish.class));
cards.add(new SetCardInfo("Quirion Dryad", 198, Rarity.UNCOMMON, mage.cards.q.QuirionDryad.class));
cards.add(new SetCardInfo("Rain of Revelation", 61, Rarity.UNCOMMON, mage.cards.r.RainOfRevelation.class));
cards.add(new SetCardInfo("Runed Halo", 32, Rarity.RARE, mage.cards.r.RunedHalo.class));
cards.add(new SetCardInfo("Shipwreck Dowser", 71, Rarity.UNCOMMON, mage.cards.s.ShipwreckDowser.class));
cards.add(new SetCardInfo("Storm Caller", 335, Rarity.COMMON, mage.cards.s.StormCaller.class));
cards.add(new SetCardInfo("Teferi's Protege", 77, Rarity.COMMON, mage.cards.t.TeferisProtege.class));
cards.add(new SetCardInfo("Tormod's Crypt", 241, Rarity.UNCOMMON, mage.cards.t.TormodsCrypt.class));
cards.add(new SetCardInfo("Ugin, the Spirit Dragon", 1, Rarity.MYTHIC, mage.cards.u.UginTheSpiritDragon.class));
cards.add(new SetCardInfo("Wildwood Patrol", 339, Rarity.COMMON, mage.cards.w.WildwoodPatrol.class));
}
}

View file

@ -117,6 +117,9 @@ public class VerifyCardDataTest {
// subtype
skipListCreate(SKIP_LIST_SUBTYPE);
skipListAddName(SKIP_LIST_SUBTYPE, "UGL", "Miss Demeanor");
// the following is temporary
subtypesToIgnore.add("Dog");
subtypesToIgnore.add("Hound");
// number
skipListCreate(SKIP_LIST_NUMBER);

View file

@ -24,6 +24,11 @@ public class PermanentsOnBattlefieldCount implements DynamicValue {
this(filter, 1);
}
/**
*
* @param filter
* @param multiplier
*/
public PermanentsOnBattlefieldCount(FilterPermanent filter, Integer multiplier) {
this.filter = filter;
this.multiplier = multiplier;

View file

@ -119,6 +119,7 @@ public enum SubType {
DEVIL("Devil", SubTypeSet.CreatureType),
DINOSAUR("Dinosaur", SubTypeSet.CreatureType), // With Ixalan now being spoiled, need this to be selectable
DJINN("Djinn", SubTypeSet.CreatureType),
DOG("Dog", SubTypeSet.CreatureType),
DRAGON("Dragon", SubTypeSet.CreatureType),
DRAKE("Drake", SubTypeSet.CreatureType),
DREADNOUGHT("Dreadnought", SubTypeSet.CreatureType),
@ -175,7 +176,6 @@ public enum SubType {
HOMUNCULUS("Homunculus", SubTypeSet.CreatureType),
HORROR("Horror", SubTypeSet.CreatureType),
HORSE("Horse", SubTypeSet.CreatureType),
HOUND("Hound", SubTypeSet.CreatureType),
HUMAN("Human", SubTypeSet.CreatureType),
HUNTER("Hunter", SubTypeSet.CreatureType),
HUTT("Hutt", SubTypeSet.CreatureType, true), // Star Wars

View file

@ -1,31 +1,29 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
/**
*
* @author spjspj
*/
public final class HoundToken extends TokenImpl {
public final class DogToken extends TokenImpl {
public HoundToken() {
super("Hound", "1/1 green Hound creature token");
public DogToken() {
super("Dog", "1/1 green Dog creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.HOUND);
subtype.add(SubType.DOG);
color.setGreen(true);
power = new MageInt(1);
toughness = new MageInt(1);
}
public HoundToken(final HoundToken token) {
private DogToken(final DogToken token) {
super(token);
}
public HoundToken copy() {
return new HoundToken(this);
public DogToken copy() {
return new DogToken(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.game.permanent.token;
import mage.MageInt;
@ -13,11 +12,11 @@ import mage.constants.SuperType;
public final class MowuToken extends TokenImpl {
public MowuToken() {
super("Mowu", "legendary 3/3 green Hound creature token named Mowu");
super("Mowu", "legendary 3/3 green Dog creature token named Mowu");
cardType.add(CardType.CREATURE);
color.setGreen(true);
this.addSuperType(SuperType.LEGENDARY);
subtype.add(SubType.HOUND);
subtype.add(SubType.DOG);
power = new MageInt(3);
toughness = new MageInt(3);
}

View file

@ -37438,5 +37438,52 @@ Gyruda, Doom of Depths|Ikoria: Lair of Behemoths|384|R|{4}{U/B}{U/B}|Legendary C
Mysterious Egg|Ikoria: Lair of Behemoths|385|C|{1}|Creature - Egg|0|2|Whenever this creature mutates, put a +1/+1 counter on it.|
Dirge Bat|Ikoria: Lair of Behemoths|386|R|{2}{B}{B}|Creature - Bat|3|3|Mutate {4}{B}{B}$Flash$Flying$Whenever this creature mutates, destroy target creature or planeswalker an opponent controls.|
Crystalline Giant|Ikoria: Lair of Behemoths|387|R|{3}|Artifact Creature - Giant|3|3|At the beginning of combat on your turn, choose a kind of counter at random that Crystalline Giant doesn't have on it from among flying, first strike, deathtouch, hexproof, lifelink, menace, reach, trample, vigilance, or +1/+1. Put a counter of that kind on Crystalline Giant.|
Ugin, the Spirit Dragon|Core Set 2021|1|M|{8}|Legendary Planeswalker - Ugin|7|+2: Ugin, the Spirit Dragon deals 3 damage to any target.$X: Exile each permanent with converted mana cost X or less that's one or more colors.$10: You gain 7 life, draw seven cards, then put up to seven permanent cards from your hand onto the battlefield.|
Baneslayer Angel|Core Set 2021|4|M|{3}{W}{W}|Creature - Angel|5|5|Flying, first strike, lifelink, protection from Demons and from Dragons|
Mangara, the Diplomat|Core Set 2021|27|M|{3}{W}|Legendary Creature - Human Cleric|2|4|Lifelink$Whenever an opponent attacks with creatures, if two or more of those creatures are attacking you and/or a planeswalker you control, draw a card.$Whenever an opponent casts their second spell each turn, draw a card.|
Pack Leader|Core Set 2021|29|R|{1}{W}|Creature - Dog|2|2|Other Dogs you control get +1/+1.$Whenever Pack Leader attacks, prevent all combat damage that would be dealt this turn to Dogs you control.|
Runed Halo|Core Set 2021|32|R|{W}{W}|Enchantment|||As Runed Halo enters the battlefield, choose a card name.$You have protection from the chosen name.|
Jeskai Elder|Core Set 2021|53|U|{1}{U}|Creature - Human Monk|1|2|Prowess$Whenever Jeskai Elder deals combat damage to a player, you may draw a card. If you do, discard a card.|
Rain of Revelation|Core Set 2021|61|U|{3}{U}|Instant|||Draw three cards, then discard a card.|
Shipwreck Dowser|Core Set 2021|71|U|{3}{U}{U}|Creature - Merfolk Wizard|3|3|Prowess$When Shipwreck Dowser enters the battlefield, return target instant or sorcery card from your graveyard to your hand.|
Teferi, Master of Time|Core Set 2021|75|M|{2}{U}{U}|Legendary Planeswalker - Teferi|3|You may activate loyalty abilities of Teferi, Master of Time on any player's turn any time you could cast an instant.$+1: Draw a card, then discard a card.$3: Target creature you don't control phases out.$10: Take two extra turns after this one.|
Teferi's Ageless Insight|Core Set 2021|76|R|{2}{U}{U}|Legendary Enchantment|||If you would draw a card except the first one you draw in each of your draw steps, draw two cards instead.|
Teferi's Protege|Core Set 2021|77|C|{2}{U}|Creature - Human Wizard|2|3|{1}{U}, {T}: Draw a card, then discard a card.|
Teferi's Tutelage|Core Set 2021|78|U|{2}{U}|Enchantment|||When Teferi's Tutelage enters the battlefield, draw a card, then discard a card.$Whenever you draw a card, target opponent mills two cards.|
Grim Tutor|Core Set 2021|103|M|{1}{B}{B}|Sorcery|||Search your library for a card and put that card into your hand, then shuffle your library. You lose 3 life.|
Liliana, Waker of the Dead|Core Set 2021|108|M|{2}{B}{B}|Legendary Planeswalker - Liliana|4|+1: Each player discards a card. Each opponent who can't loses 3 life.$3: Target creature gets -X/-X until end of turn, where X is the number of cards in your graveyard.$7: You get an emblem with "At the beginning of combat on your turn, put target creature card from a graveyard onto the battlefield under your control. It gains haste."|
Peer into the Abyss|Core Set 2021|117|R|{4}{B}{B}{B}|Sorcery|||Target player draws cards equal to half the number of cards in their library and loses half their life. Round up each time.|
Vito, Thorn of the Dusk Rose|Core Set 2021|127|R|{2}{B}|Legendary Creature - Vampire Cleric|1|3|Whenever you gain life, target opponent loses that much life.${3}{B}{B}: Creatures you control gain lifelink until end of turn.|
Double Vision|Core Set 2021|142|R|{3}{R}{R}|Enchantment|||Whenever you cast your first instant or sorcery spell each turn, copy that spell. You may choose new targets for the copy.|
Gadrak, the Crown-Scourge|Core Set 2021|146|R|{2}{R}|Legendary Creature - Dragon|5|4|Flying$Gadrak, the Crown-Scourge can't attack unless you control four or more artifacts.$At the beginning of your end step, create a Treasure token for each nontoken creature that died this turn.|
Azusa, Lost but Seeking|Core Set 2021|173|R|{2}{G}|Legendary Creature - Human Monk|1|2|You may play two additional lands on each of your turns.|
Fierce Empath|Core Set 2021|181|U|{2}{G}|Creature - Elf|1|1|When Fierce Empath enters the battlefield, you may search your library for a creature card with converted mana cost 6 or greater, reveal it, put it into your hand, then shuffle your library.|
Primal Might|Core Set 2021|197|R|{X}{G}|Sorcery|||Target creature you control gets +X/+X until end of turn. Then it fights up to one target creature you don't control.|
Quirion Dryad|Core Set 2021|198|U|{1}{G}|Creature - Dryad|1|1|Whenever you cast a white, blue, black, or red spell, put a +1/+1 counter on Quirion Dryad.|
Indulging Patrician|Core Set 2021|219|U|{1}{W}{B}|Creature - Vampire Noble|1|4|Flying$Lifelink$At the beginning of your end step, if you gained 3 or more life this turn, each opponent loses 3 life.|
Chromatic Orrery|Core Set 2021|228|M|{7}|Legendary Artifact|||You may spend mana as though it were mana of any color.${T}, Add {C}{C}{C}{C}{C}.${5}, {T}: Draw a card for each color among permanents you control.|
Sparkhunter Masticore|Core Set 2021|240|R|{3}|Artifact Creature - Masticore|3|4|As an additional cost to cast this spell, discard a card.$Protection from planeswalkers${1}: Sparkhunter Masticore deals 1 damage to target planeswalker.${3}: Sparkhunter Masticore gains indestructible until end of turn.|
Tormod's Crypt|Core Set 2021|241|U|{0}|Artifact|||{T}, Sacrifice Tormod's Crypt: Exile all cards from target player's graveyard.|
Rin and Seri, Inseparable|Core Set 2021|278|M|{1}{R}{G}{W}|Legendary Creature - Dog Cat|4|4|Whenever you cast a Dog spell, create a 1/1 green Cat creature token.$Whenever you cast a Cat spell, create a 1/1 white Dog creature token.${R}{G}{W}: Rin and Seri, Inseparable deals damage to any target equal to the number of Dogs you control. You gain life equal to the number of Cats you control.|
Island|Core Set 2021|310|C||Basic Land - Island|||({T}: Add {U}.)|
Containment Priest|Core Set 2021|314|R|{1}{W}|Creature - Human Cleric|2|2|Flash$If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead.|
Basri, Devoted Paladin|Core Set 2021|320|M|{4}{W}{W}|Legendary Planeswalker - Basri|4|+1: Put a +1/+1 counter on up to one target creature. It gains vigilance until end of turn.$1: Whenever a creature attacks this turn, put a +1/+1 counter on it.$6: Creatures you control get +2/+2 and gain flying until end of turn.|
Adherent of Hope|Core Set 2021|321|C|{1}{W}|Creature - Human Soldier|2|1|At the beginning of combat on your turn, if you control a Basri planeswalker, put a +1/+1 counter on Adherent of Hope.|
Basri's Aegis|Core Set 2021|322|R|{2}{W}{W}|Sorcery|||Put a +1/+1 counter on each of up to two target creatures. You may search your library and/or graveyard for a card named Basri, Devoted Paladin, reveal it, and put it into your hand. If you search your library this way, shuffle it.|
Sigiled Contender|Core Set 2021|323|U|{3}{W}|Creature - Human Warrior|3|3|Sigiled Contender has lifelink as long as it has a +1/+1 counter on it.|
Teferi, Timeless Voyager|Core Set 2021|324|M|{4}{U}{U}|Legendary Planeswalker - Teferi|4|+1: Draw a card.$3: Put target creature on top of its owner's library.$8: Each creature target opponent controls phases out. Until the end of your next turn, they can't phase in.|
Historian of Zhalfir|Core Set 2021|325|U|{2}{U}{U}|Creature - Human Wizard|3|3|Whenever Historian of Zhalfir attacks, if you control a Teferi planeswalker, draw a card.|
Mystic Skyfish|Core Set 2021|326|C|{2}{U}|Creature - Fish|3|1|Whenever you draw your second card each turn, Mystic Skyfish gains flying until end of turn.|
Teferi's Wavecaster|Core Set 2021|327|R|{3}{U}{U}|Creature - Merfolk Wizard|3|3|Flash$When Teferi's Wavecaster enters the battlefield, you may search your library and/or graveyard for a card named Teferi, Timeless Voyager, reveal it, and put it into your hand. If you search your library this way, shuffle it.|
Liliana, Death Mage|Core Set 2021|328|M|{4}{B}{B}|Legendary Planeswalker - Liliana|4|+1: Return up to one target creature card from your graveyard to your hand.$3: Destroy target creature. Its controller loses 2 life.$7: Target opponent loses 2 life for each creature card in their graveyard.|
Liliana's Scorn|Core Set 2021|329|R|{3}{B}{B}|Sorcery|||Destroy target creature. You may search your library and/or graveyard for a card named Liliana, Death Mage, reveal it, and put it into your hand. If you search your library this way, shuffle it.|
Liliana's Scrounger|Core Set 2021|330|U|{2}{B}|Creature - Human Wizard|3|2|At the beginning of each end step, if a creature died this turn, you may put a loyalty counter on a Liliana planeswalker you control.|
Spirit of Malevolence|Core Set 2021|331|C|{1}{B}|Creature - Spirit|2|1|When Spirit of Malevolence dies, each opponent loses 1 life and you gain 1 life.|
Chandra, Flame's Catalyst|Core Set 2021|332|M|{4}{R}{R}|Legendary Planeswalker - Chandra|5|+1: Chandra, Flame's Catalyst deals 3 damage to each opponent.$2: You may cast target red instant or sorcery card from your graveyard. If that spell would be put into your graveyard this turn, exile it instead.$8: Discard your hand, then draw seven cards. Until end of turn, you may cast spells from your hand without paying their mana costs.|
Chandra's Firemaw|Core Set 2021|333|R|{3}{R}{R}|Creature - Hellion|4|2|Haste$When Chandra's Firemaw enters the battlefield, you may search your library and/or graveyard for a card named Chandra, Flame's Catalyst, reveal it, and put it into your hand. If you search your library this way, shuffle it.|
Keral Keep Disciples|Core Set 2021|334|U|{2}{R}{R}|Creature - Human Monk|4|3|Whenever you activate a loyalty ability of a Chandra planeswalker, Keral Keep Disciples deals 1 damage to each opponent.|
Storm Caller|Core Set 2021|335|C|{2}{R}|Creature - Ogre Shaman|3|2|When Storm Caller enters the battlefield, it deals 2 damage to each opponent.|
Garruk, Savage Herald|Core Set 2021|336|M|{4}{G}{G}|Legendary Planeswalker - Garruk|5|+1: Reveal the top card of your library. If it's a creature card, put it into your hand. Otherwise, put it on the bottom of your library.$2: Target creature you control deals damage equal to its power to another target creature.$7: Until end of turn, creatures you control gain "You may have this creature assign its combat damage as though it weren't blocked."|
Garruk's Warsteed|Core Set 2021|337|R|{3}{G}{G}|Creature - Rhino|3|5|Vigilance$When Garruk's Warsteed enters the battlefield, you may search your library and/or graveyard for a card named Garruk, Savage Herald, reveal it, and put it into your hand. If you search your library this way, shuffle it.|
Predatory Wurm|Core Set 2021|338|U|{3}{G}|Creature - Wurm|4|4|Vigilance$Predatory Wurm gets +2/+2 as long as you control a Garruk planeswalker.|
Wildwood Patrol|Core Set 2021|339|C|{2}{G}|Creature - Centaur Scout|4|2|Trample|